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\n",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\n",ans); return 0; }