*【链表+堆】序列m个连续和最大[CH1812]生日礼物
该比赛已结束,您无法在比赛模式下递交该题目。您可以点击“在题库中打开”以普通模式查看和递交本题。
Description
0x10基本数据结构(练习)13:生日礼物[CH1812] ## 【题意】 从 $N$ 个元素的序列 $A_i$ 中选择不超过 $M$ 个连续的部分,使得所选元素之和最大。【输入格式】
第一行两个整数 N,M(0 \le N,M \le 10^5)。
第二行 个整数 。
【输出格式】
输出一个整数,表示答案。
【输入样例】
5 2
2 -3 2 -1 2
【输出样例】
5
Hint
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,int> PLI;
const int N=1e5+100;
LL a[N];
int L[N],R[N],del[N];
priority_queue<PLI,vector<PLI>,greater<PLI>> q;
void remove(int x)
{
L[R[x]]=L[x];
R[L[x]]=R[x];
del[x]=1;
}
int main()
{
int n,m;scanf("%d%d",&n,&m);
int k=0;
for(int i=1;i<=n;i++)
{
LL x;scanf("%lld",&x);
if(x!=0)
{
if(!k||a[k]*x<0)a[++k]=x;
else a[k]+=x;
}
}
n=k;
LL ans=0,cnt=0;
for(int i=1;i<=n;i++)
{
L[i]=i-1,R[i]=i+1;
q.push({abs(a[i]),i});
if(a[i]>0)ans+=a[i],cnt++;
}
memset(del,0,sizeof(del));
while(cnt>m)
{
while(del[q.top().second])q.pop();
PLI no=q.top();q.pop();
int x=no.second;
if(a[x]>0||(L[x]!=0&&R[x]!=n+1))
{
ans-=abs(a[x]);
a[x]+=a[L[x]]+a[R[x]];
q.push({abs(a[x]),x});
remove(L[x]);
remove(R[x]);
cnt--;
}
}
printf("%d",ans);
return 0;
}