据说这题是种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 }