Codeforces 1144G(dp)

据说这题是种dp的套路?然后被我国红名神仙(南大Roundgod)贪心了,不过思路上非常相近了,故而可贪吧。

设的dp[i][0]是:如果把第i个数放在上升序列里了,那么下降序列结尾的那个最大是多少;同理,dp[i][1]是:如果把第i个数放在下降序列里了,那么上升序列结尾的那个最大是多少。

个人yy,这样设的巧妙之处大概就是我们想转移第i个时,需要比较一下大小才能看第i个能不能插入某个序列,而你发现这个dp明明含义是把i放上升里了,记录的却是下降的结尾——这就使得我们拿到i+1个时,想放上升时就跟a[i]比,想放下降时就跟dp[i][0]比,这就可以转移了,其他几种情况同理。

尽量让下降序列的结尾更大,上升序列的结尾更小,才会“家有余粮,心里不慌”,对后面的数列更具包容性。这大概也是可以贪心的哲学道理吧(大雾

 

 1 const int maxn = 2e5 + 5;
 2 int n, a[maxn];
 3 int pre[maxn][2];
 4 
 5 void print(int i, int pos) {
 6     if (i) {
 7         print(i - 1, pre[i][pos]);
 8     }
 9     printf("%d ", pos);
10 }
11 
12 int main() {
13     read(n);
14     rep(i, 0, n - 1)    read(a[i]);
15 
16     vector<vector<int>>dp(n, vector<int>({-inf, inf}));
17 
18     dp[0][0] = inf, dp[0][1] = -inf;
19     rep(i, 1, n - 1) {
20         //add to increase
21         if (a[i] > a[i - 1] && dp[i][0] < dp[i - 1][0]) {
22             dp[i][0] = dp[i - 1][0];
23             pre[i][0] = 0;
24         }
25         if (a[i] > dp[i - 1][1] && dp[i][0] < a[i - 1]) {
26             dp[i][0] = a[i - 1];
27             pre[i][0] = 1;
28         }
29         //add to decrease
30         if (a[i] < a[i - 1] && dp[i][1] > dp[i - 1][1]) {
31             dp[i][1] = dp[i - 1][1];
32             pre[i][1] = 1;
33         }
34         if (a[i] < dp[i - 1][0] && dp[i][1] > a[i - 1]) {
35             dp[i][1] = a[i - 1];
36             pre[i][1] = 0;
37         }
38     }
39 
40     int pos = -1;
41     if (dp[n - 1][0] != -inf)    pos = 0;
42     if (dp[n - 1][1] != inf)    pos = 1;
43 
44     if (pos < 0)    puts("NO");
45     else {
46         puts("YES");
47         print(n - 1, pos);
48     }
49 
50     return 0;
51 }

 

posted @ 2019-04-02 19:32  AlphaWA  阅读(238)  评论(0编辑  收藏  举报