AcWing 1090. 绿色通道
/*
数组没开够,爆零两行泪
longlong开成int,爆零两行泪
多组忘清空,爆零两行泪
dp 没初值,爆零两行泪
深搜没边界,爆零两行泪
广搜忘出队,爆零两行泪
输入没加 &,爆零两行泪
模数没看见,爆零两行泪
-1 不输出,爆零两行泪
越界不特判,爆零两行泪
线段树开一倍,爆零两行泪
无向变有向,爆零两行泪
题意没审清,爆零两行泪
文件名起错,爆零两行泪
调试忘删除,爆零两行泪
没用freopen,爆零两行泪
*/
#include<bits/stdc++.h>
using namespace std;
const int N=50010;
int n,m;
int q[N],f[N],w[N];
bool check(int limit){
int hh=0,tt=0;
for(int i=1;i<=n;i++){
if(q[hh]<i-limit-1) hh++;//要减一,闭区间
f[i]=f[q[hh]]+w[i];
while(hh<=tt&&f[q[tt]]>=f[i]) tt--;
q[++tt]=i;
}
for(int i=n-limit;i<=n;i++){
if(f[i]<=m) return true;
}
return false;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>w[i];
int l=0,r=n;
while(l<r){
int mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<r<<endl;
return 0;
}
/*
和 p1089 几乎一样,就是套个二分
每次二分一下最长空段的长度
f[i]表示写第i个题,并保证前面的题都不会超出要求,所需的最小代价
同样,q[hh]维护可选区间的最小代价的下标
复杂度O(nlogn)
*/