BZOJ4385 : [POI2015]Wilcze doły

求出前缀和$s$,设$f[i]=s[i+d-1]-s[i-1]$。

从左到右枚举的右端点$i$,左端点$j$满足单调性,若$s[i]-s[j-1]-\max(区间内最大的f)\leq p$,则可行。

用单调队列维护即可,时间复杂度$O(n)$。

 

#include<cstdio>
#define N 2000010
int n,d,i,j,q[N],h,t,ans;long long p,sum,s[N],f[N];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
int main(){
  read(n),scanf("%lld",&p),read(d);
  for(i=1;i<=n;i++)read(j),s[i]=s[i-1]+j;
  for(i=1;i<=n-d+1;i++)f[i]=s[i+d-1]-s[i-1];
  for(i=d,j=h=1;i<=n;i++){
    while(h<=t&&f[q[t]]<=f[i-d+1])t--;q[++t]=i-d+1;
    while(s[i]-s[j-1]-f[q[h]]>p)for(j++;q[h]<j;h++);
    if(i-j+1>ans)ans=i-j+1;
  }
  return printf("%d",ans),0;
}

  

转载于:https://www.cnblogs.com/clrs97/p/5271149.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值