BZOJ 4385 洛谷3594 POI2015 WIL-Wilcze doły

【题解】  

  手残写错调了好久QAQ......

  洛谷的数据似乎比较水。。

  n个正整数!!这很重要

  这道题是个类似two pointer的思想,外加一个单调队列维护当前区间内长度为d的子序列中元素之和的最大值。

  枚举右端点,如果左端点到右端点的元素和减去区间内长为d的子序列中元素和的最大值,大于给定的P,那么就把左端点向右挪。

  

#include<cstdio>
#include<algorithm>
#define N 2000010
#define rg register
#define LL long long
using namespace std;
LL n,m,d,a[N],h[N],s[N],p[N],tmp;
int ans;
inline LL read(){
	LL k=0; char c=getchar();
	while(c<'0'||c>'9')c=getchar();
	while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
	return k;
}
inline int max(int x,int y){
	return x>y?x:y;
}
int main(){
	n=read(); m=read(); ans=d=read();
	for(rg int i=1;i<=n;i++) a[i]=read(),s[i]=s[i-1]+a[i];
	if(n<=d) return printf("%d
",d),0;
	int l=1,front=1,rear=0;
	for(rg int i=d+1;i<=n;i++){
		tmp=s[i]-s[i-d];
		while(front<=rear&&h[rear]<=tmp) rear--;
		h[++rear]=tmp; p[rear]=i-d+1;
		while(p[front]<l&&front<=rear) front++;
		while(l<=i-d+1){
			if(front<=rear) tmp=s[i]-s[l-1]-h[front];
			else tmp=s[i]-s[l-1];
			if(tmp<=m){
				ans=max(ans,i-l+1);
				break;
			}
			else l++;
		}
		tmp=s[i]-s[l-1];
	}
	printf("%d
",ans);
	return 0;
}

  

原文地址:https://www.cnblogs.com/DriverLao/p/8626035.html