洛谷【P1714】切蛋糕
浅谈队列:https://www.cnblogs.com/AKMer/p/10314965.html
题目传送门:https://www.luogu.org/problemnew/show/P1714
区间和转化为前缀和相减的形式,那么以\(i\)结尾的区间最大和就是\(sum[i]-sum[x]\),其中\(x\)是满足\(i-x<=k\)的位置里\(sum\)最小的一个。
如果一个数位置比队尾小权值还比队尾小,那么队尾就没用了,可以踢掉了。
如果队头与当前位置距离超过\(k\),那么就把队头踢掉。
最小值就是队头记录的那个。
时间复杂度:\(O(nlogn)\)
空间复杂度:\(O(n)\)
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=5e5+5;
int n,k,head,tail,ans;
int a[maxn],sum[maxn],list[maxn];
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
int main() {
n=read(),k=read();
for(int i=1;i<=n;i++)
a[i]=read(),sum[i]=sum[i-1]+a[i];
for(int i=1;i<=n;i++) {
while(head!=tail&&sum[list[tail-1]]>sum[i])tail--;
while(head!=tail&&i-list[head]>k)head++;
list[tail++]=i;ans=max(ans,sum[i]-sum[list[head]]);
}
printf("%d\n",ans);
return 0;
}