在一段k+1的数字中,一定有一个数字是删除的,现在逆向思维,我们要计算出逆向过程中,即计算出删除最小的和是多少。
利用单调队列进行辅助
# include <algorithm>
# include <iostream>
# include <cstring>
# include <cstdio>
# include <queue>
# include <cmath>
# include <ctime>
# define R register
# define LL long long
using namespace std;
LL tot,d,n,k;
LL p[100010],head = 1,tail = 1;
LL q[100010],f[100010],ans;
inline void in(R LL &a){ //输入部分的处理
R char c = getchar();R LL x=0,f=1;
while(!isdigit(c)){if(c == '-') f=-1; c =getchar();}
while(isdigit(c)) x = (x<<1)+(x<<3)+c-'0',c = getchar();
a = x*f;
}
inline void maxx(R LL &a,const LL b){a>b? 0:a=b;}
inline LL yg(){
// freopen("bronlily.in","r",stdin);
// freopen("bronlily.out","w",stdout);
in(n),in(k);
for(R int i=1; i<=n; ++i)
{
in(d);
tot += d; //总数记录
f[i] = q[head]+1LL*d; //f[i]表示前i个数删除的最小的和
//加上d,这里是有点晕的,但是应该可以这么想:因为之前head=1,所以 q[head]=0,不影响,
//当head后面开始递增,说明距离已经拉大 ,就需要再加上d
//理解为:前面没加,后面距离变大,开始加
while(head<=tail&&q[tail]>=f[i]) tail--; //head<=tail,说明是有元素的,并且尾部元素大于f[i]说明,尾部元素不可能是最小的,出队
q[++tail] = f[i],p[tail] = i; //f[i]入队
while(head<=tail&&p[head]<i-k) head++; //如果队首的位置太远,需要满足小于k
}
for(R int i=n-k; i<=n; ++i) maxx(ans,1LL*tot-1LL*f[i]); //找到最后k个f[i]元素中最小的,即是答案
printf("%lld",ans);
return 0;
}
LL youngsc = yg();
int main(){;}