原題連結
題解
不能連續選k個元素 \(\to\) 任意每k個元素就有一個不選 \(\to\) 每k個點就有一個斷點
\(\to\) 每個點都有可能是斷點 \(\to\) dp求解
\(sol.1\)
令 \(f[i]\) 為第i個點為斷點且為結尾的最大值
則 \(f[i]=max(f[j]+sum[j+1,i-1])\)
\(sol.2\)
至少每隔k個點就取一個點,取點和的最小值
\(code1\),優先佇列,\(O(n·logn)\)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct node
{
ll v,x;
bool operator <(const node &b)const {return b.v<v;}
};
ll dp[1000005]={0};
ll a[1000005];
int main()
{
ll n,k,sum=0;
cin>>n>>k;
for(ll i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
}
priority_queue<node> q;
ll ans=2e18;
for(ll i=1;i<=n;i++)
{
q.push({dp[i-1],i-1});
while(q.size()&&i-q.top().x>k+1) q.pop();
dp[i]=a[i];
if(q.size()) dp[i]+=q.top().v;
if(i+k>=n)ans=min(ans,dp[i]);
//cout<<dp[i]<<endl;
}
cout<<sum-ans;
return 0;
}
\(code2\),單調佇列,\(O(n)\)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll sum[1000005]={0},f[100005]={0};
ll a[1000005];
int main()
{
ll n,k;
cin>>n>>k;
for(ll i=1;i<=n;i++)
{
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
deque<ll> q;
q.push_back(0);
for(int i=1;i<=n;i++)
{
if(q.size()&&i-q.front()>k+1)q.pop_front();
if(q.size()) f[i]=f[q.front()]+sum[i-1]-sum[q.front()];
while(q.size()&&f[q.back()]-sum[q.back()]<=f[i]-sum[i]) q.pop_back();
q.push_back(i);
//cout<<f[i]<<endl;
}
if(q.size()&&n-q.front()>k) q.pop_front();
cout<<f[q.front()]+sum[n]-sum[q.front()];
return 0;
}