洛谷【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;
}
posted @ 2019-01-24 21:28  AKMer  阅读(187)  评论(0编辑  收藏  举报