P3594 WIL
题意很简化了已经
刚拿到题的时候我其实想的就是在一段大区间(答案区间)中找到长度为d的区间最大的区间,然后答案就是大区间的区间和减去长度为d的区间和,这个大区间找的时候用双指针,r一直右移,如果区间和减去长度为d的区间和大于了p,那左指针就右移,就这样一直找;
但是有两个问题,就是我怎么找这个大区间中长为d的最大区间,可以先提前预处理前缀和,sum[r]-sum[r-d]就是你要维护的值,而单调队列离要存下标(因为后边要用),另一个问题是,如果大区间左指针右移之后,你本来维护的那个长为d的区间就出了大区间了,那怎么解决?(我当时就是因为单调队列存的不是下标,然后就不会搞了,因为我没法判断它是不是出了大区间)因为单调队列存的是下标,所以,每次左指针右移时,都要while判断你存的那个区间是不是小于左指针即可,如果小于,那单调队列就出队头;
每次新加一个数都统计最大区间长度即可
下面是代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e6+10;
int n,p,d;
int q[N],a[N],ans,l,sum[N],t,h;
signed main()
{
cin>>n>>p>>d;
for(int i=1;i<=n;i++)scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
ans=d,q[t]=d,l=1;
for(int i=d+1;i<=n;i++)
{
while(h<=t&&sum[i]-sum[i-d]>sum[q[t]]-sum[q[t]-d])--t;
q[++t]=i;
while(h<=t&&sum[i]-sum[l-1]-sum[q[h]]+sum[q[h]-d]>p)
{
++l;
while(h<=t&&q[h]-d+1<l)++h;
}
ans = max(ans,i-l+1);
}
printf("%lld", ans);
return 0;
}
标签:右移,int,sum,WIL,队列,P3594,区间,指针
From: https://www.cnblogs.com/Eternal-QX/p/16879768.html