题解
不能连续选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;
}
标签:P2034,数字,ll,long,选择,front,断点,sum,dp
From: https://www.cnblogs.com/pure4knowledge/p/18062924