[bzoj4385][POI2015]Wilcze doły_单调队列

Wilcze doły bzoj-4385 POI-2015

题目大意:给定一个n个数的序列,可以将连续的长度不超过d的区间内所有数变成0,求最长的一段区间,使得区间和不超过p。

注释:$1\le n,m\le 10^6$,$1\le a_i$。


想法:感觉自己就没会过单调队列... ...

这个题,因为权值都为正,所以我们就相当于把长度为d的区间变成0。

又因为权值正,所以在右端点松弛1到n的时候左端点是单调的。

这样的话我们只需要枚举右端点的时候求出当前右端点和左端点之间的区间最大值然后把它变成0,这个过程可以用单调队列维护。

最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 2000005 
typedef long long ll;
using namespace std;
int n,d,q[N]; ll s[N],p;
int main()
{
	scanf("%d%lld%d",&n,&p,&d); int i; ll x;
	for(i=1;i<=n;i++) scanf("%lld",&x),s[i]=s[i-1]+x;
	int ans=d,head=1,tail=0,j=0;
	for(i=d;i<=n;i++)
	{
		while(head<=tail && s[i]-s[i-d]>s[q[tail]]-s[q[tail]-d]) tail--;
		q[++tail]=i;
		while(s[i]-s[j]-s[q[head]]+s[q[head]-d]>p)
		{
			j++;
			if(q[head]-d<j) head++;
		}
		ans=max(ans,i-j);
	}
	printf("%d\n",ans);
	return 0;
}

小结:单调队列要重学了...

猜你喜欢

转载自www.cnblogs.com/ShuraK/p/9393919.html