#10181. 「一本通 5.5 练习 2」绿色通道

${\color{cyan}{>>Question}}$

二分+$dp$(与跳房子类似)

二分答案(窗口大小),$dp$确定是否可行

$f[i]$表示到$i$($i$选)花的最少时间

$$f[i] = min_{j\in[i-d-1,i-1]}\left \{ f[j] \right \}+a[i]$$

$d$为二分的答案

注意统计是要$f[n+1]>t$才$return\;0$

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 #define ll long long
 6 using namespace std; 
 7 
 8 template <typename T> void in(T &x) {
 9     x = 0; T f = 1; char ch = getchar();
10     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
11     while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();}
12     x *= f;
13 }
14 
15 template <typename T> void out(T x) {
16     if(x < 0) x = -x , putchar('-');
17     if(x > 9) out(x/10);
18     putchar(x%10 + 48);
19 }
20 //-------------------------------------------------------
21 
22 const int N = 5e4+7;
23 int n,t;
24 int a[N],f[N];
25 int q[N],hd,tl,lst;
26 
27 bool chk(int d) {
28     memset(f,0x3f,sizeof(f)); f[0] = 0;
29     hd = 1,tl = 0,lst = 0; int i;
30     for(i = 1;i <= n+1; ++i) {
31         while(lst < i-d-1) ++lst;
32         for(;lst < i; ++lst) {
33             while(hd <= tl && f[q[tl]] > f[lst]) --tl;//debug --tl -> --q[tl]
34             q[++tl] = lst;
35         }
36         while(hd <= tl && q[hd] < i-d-1) ++hd;
37         f[i] = f[q[hd]] + a[i];
38         //if(f[i] > t) return 0;//debug
39     }
40     if(f[n+1] > t) return 0;//debug 
41     return 1;
42 }
43 
44 void bs_ans() {
45     int l = 0,r = n,ans;
46     while(l <= r) {
47         int mid = (l+r)>>1;
48         if(chk(mid)) ans = mid,r = mid-1;
49         else l = mid+1;
50     }
51     out(ans);
52 }
53 
54 int main() {
55     in(n); in(t); int i;
56     for(i = 1;i <= n;++i) in(a[i]);
57     bs_ans();
58     return 0;
59 }

 

posted @ 2019-08-19 11:01  陈星卿  阅读(369)  评论(0编辑  收藏  举报