luogu P3594 [POI2015]WIL-Wilcze doły 单调队列dp+双指针
#include<cstdio> #include<iostream> using namespace std; typedef long long ll; const int N=2e6+5; ll q[N]; ll sum[N],a[N],n,p,d; ll l,r;//维护区间 ll hh,tt;//维护队列中的长度为d的最大的区间 ll ans; //hh,tt维护单调队列 //l,r双指针,以r做循环变量 //q[]代表单调队列的元素对应编号,也可用dequeue来写 int main() { scanf("%lld%lld%lld",&n,&p,&d); for(int i = 1; i<=n; ++i) scanf("%lld",&a[i]),sum[i] += sum[i-1]+a[i]; ans = d; tt = 1; hh = 1; l = 1; q[tt++] = d; //在一个区间中寻找sum[i]-sum[i-d]]的最大值 //队列中的是 区间 中 长度为d 的最大值 的右端点 for(r = d+1; r<=n; ++r) { //维护长度为d的最大值 while(hh<tt&&sum[r]-sum[r-d]>sum[q[tt-1]]-sum[q[tt-1]-d]) tt--; q[tt++] = r; //维护单调队列 while(hh<tt&&sum[r]-sum[l-1]-sum[q[hh]]+sum[q[hh]-d]>p) { l++; //维护双指针 确保长度为d的在区间内,把不被包含的区间,弹出 while(hh<tt&&q[hh]-d+1<l) hh ++; } ans = max(ans,r-l+1); } printf("%lld",ans); return 0; }