分析
最大值最小,考虑二分
当状态太多,就可以考虑二分分掉一个状态;
剩下的就好办了,不过注意边界&初值
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /*********************** 2 User:Mandy.H.Y 3 Language:c++ 4 Problem:loj 10181 5 Algorithm: 6 ***********************/ 7 8 #include<bits/stdc++.h> 9 10 using namespace std; 11 12 const int maxn = 5e4 + 5; 13 14 int n,t; 15 int a[maxn],q[maxn]; 16 int dp[maxn][3]; 17 18 template<class T>inline void read(T &x){ 19 x = 0;bool flag = 0;char ch = getchar(); 20 while(!isdigit(ch)) flag |= ch == '-',ch = getchar(); 21 while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar(); 22 if(flag) x = -x; 23 } 24 25 template<class T>void putch(const T x){ 26 if(x > 9) putch(x / 10); 27 putchar(x % 10 | 48); 28 } 29 30 template<class T>void put(const T x){ 31 if(x < 0) putchar('-'),putch(-x); 32 else putch(x); 33 } 34 35 void file(){ 36 freopen("10181.in","r",stdin); 37 freopen("10181.out","w",stdout); 38 } 39 40 void readdata(){ 41 read(n);read(t); 42 for(int i = 1;i <= n; ++ i) read(a[i]); 43 } 44 45 bool check(int x){ 46 int l,r; 47 l = r = 0; 48 dp[0][0] = 0; 49 dp[0][1] = 0;//初始化 50 for(int i = 1;i <= n; ++ i){ 51 while(l < r && q[l] < i - x) l++; 52 dp[i][1] = min(dp[i-1][0],dp[i-1][1]) + a[i]; 53 if(l < r) dp[i][0] = dp[q[l]][1]; 54 if(i <= x) dp[i][0] = 0;//注意初值 55 while(l < r && dp[q[r-1]][1] >= dp[i][1]) r--; 56 q[r++]=i; 57 } 58 int ans = min(dp[n][0],dp[n][1]); 59 if(ans <= t) return 1; 60 else return 0; 61 } 62 63 void work(){ 64 int l = 0,r = n,ans = 0; 65 while(l <= r){ 66 int mid = (l + r) >> 1; 67 if(check(mid)) ans = mid,r = mid - 1; 68 else l = mid + 1; 69 } 70 put(ans); 71 } 72 73 int main(){ 74 // file(); 75 readdata(); 76 work(); 77 return 0; 78 }