题目链接 ;
参考 ;
思路
构建状态表示:
d p [ i ] [ 1 ] dp[i][1] d p [ i ] [ 1 ] 代表在前 i 位中,若第 i 位为升序序列结尾,此时降序序列结尾的最大值;
o p [ i ] [ 1 ] op[i][1] o p [ i ] [ 1 ] 代表若第 i 位为升序序列结尾,d p [ i ] [ 1 ] dp[i][1] d p [ i ] [ 1 ] 取当前值时,第 i-1 位在升序序列 / 降序序列(1升0降);
d p [ i ] [ 0 ] dp[i][0] d p [ i ] [ 0 ] 代表在前 i 位中,若第 i 位为降序序列结尾,此时升序序列结尾的最小值;
o p [ i ] [ 0 ] op[i][0] o p [ i ] [ 0 ] 代表若第 i 位为降序序列结尾,d p [ i ] [ 0 ] dp[i][0] d p [ i ] [ 0 ] 取当前值时,第 i-1 位在升序序列 / 降序序列(1升0降);
定义初值:
d p [ i ] [ 1 ] = − i n f , d p [ i ] [ 1 ] = i n f dp[i][1]=-inf,dp[i][1]=inf d p [ i ] [ 1 ] = − i n f , d p [ i ] [ 1 ] = i n f 即每一位默认是不能参与序列的,直至转移方程时满足条件才可更新;
特殊地, d p [ 1 ] [ 1 ] = i n f , d p [ 1 ] [ 0 ] = − i n f dp[1][1]=inf,dp[1][0]=-inf d p [ 1 ] [ 1 ] = i n f , d p [ 1 ] [ 0 ] = − i n f 即第一位既可以在升序序列,也可以在降序序列;
状态转移方程:
d p [ i ] [ 1 ] = d p [ i − 1 ] [ 1 ] , o p [ i ] [ 1 ] = 1 ; ( a [ i − 1 ] < a [ i ] & & d p [ i ] [ 1 ] < d p [ i − 1 ] [ 1 ] ) dp[i][1] = dp[i - 1][1],op[i][1] = 1;(a[i - 1] < a[i] \&\& dp[i][1] < dp[i - 1][1]) d p [ i ] [ 1 ] = d p [ i − 1 ] [ 1 ] , o p [ i ] [ 1 ] = 1 ; ( a [ i − 1 ] < a [ i ] & & d p [ i ] [ 1 ] < d p [ i − 1 ] [ 1 ] ) 此位接在前位后做升序序列
d p [ i ] [ 1 ] = a [ i − 1 ] , o p [ i ] [ 1 ] = 0 ; ( d p [ i − 1 ] [ 0 ] < a [ i ] & & d p [ i ] [ 1 ] < a [ i − 1 ] ) dp[i][1] = a[i - 1],op[i][1] = 0;(dp[i - 1][0] < a[i] \&\& dp[i][1] < a[i - 1]) d p [ i ] [ 1 ] = a [ i − 1 ] , o p [ i ] [ 1 ] = 0 ; ( d p [ i − 1 ] [ 0 ] < a [ i ] & & d p [ i ] [ 1 ] < a [ i − 1 ] ) 前位做降序序列结尾,此位做升序序列结尾
d p [ i ] [ 0 ] = d p [ i − 1 ] [ 0 ] , o p [ i ] [ 0 ] = 0 ; ( a [ i − 1 ] > a [ i ] & & d p [ i ] [ 0 ] > d p [ i − 1 ] [ 0 ] ) dp[i][0] = dp[i - 1][0],op[i][0] = 0;(a[i - 1] > a[i] \&\& dp[i][0] > dp[i - 1][0]) d p [ i ] [ 0 ] = d p [ i − 1 ] [ 0 ] , o p [ i ] [ 0 ] = 0 ; ( a [ i − 1 ] > a [ i ] & & d p [ i ] [ 0 ] > d p [ i − 1 ] [ 0 ] ) 此位接在前位后做降序序列
d p [ i ] [ 0 ] = a [ i − 1 ] , o p [ i ] [ 0 ] = 1 ; ( d p [ i − 1 ] [ 1 ] > a [ i ] & & d p [ i ] [ 0 ] > a [ i − 1 ] ) dp[i][0] = a[i - 1],op[i][0] = 1;(dp[i - 1][1] > a[i] \&\& dp[i][0] > a[i - 1]) d p [ i ] [ 0 ] = a [ i − 1 ] , o p [ i ] [ 0 ] = 1 ; ( d p [ i − 1 ] [ 1 ] > a [ i ] & & d p [ i ] [ 0 ] > a [ i − 1 ] ) 前位做升序序列结尾,此位做降序序列结尾
在上面的两个限制条件中,前一个条件决定了此种情况的可行性,后一个条件决定了做出更新的必要性;
对于dp后的结果,只要 d p [ i ] [ j ] dp[i][j] d p [ i ] [ j ] 不是初始值,即代表此种情况存在可行解,通过 o p [ i ] [ j ] op[i][j] o p [ i ] [ j ] 标记的方向回溯即可;
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 #include <bits/stdc++.h> using namespace std;typedef long long ll;const int inf = 0x7f7f7f7f ;int a[200005 ];int dp[200005 ][2 ];int op[200005 ][2 ];int opt[200005 ];int main () { int n; scanf ("%d" , &n); for (int i = 1 ; i <= n; i++) scanf ("%d" , &a[i]); dp[1 ][1 ] = inf, dp[1 ][0 ] = -inf; for (int i = 2 ; i <= n; i++) { dp[i][1 ] = -inf, dp[i][0 ] = inf; if (a[i - 1 ] < a[i] && dp[i][1 ] < dp[i - 1 ][1 ]) { dp[i][1 ] = dp[i - 1 ][1 ]; op[i][1 ] = 1 ; } if (dp[i - 1 ][0 ] < a[i] && dp[i][1 ] < a[i - 1 ]) { dp[i][1 ] = a[i - 1 ]; op[i][1 ] = 0 ; } if (a[i - 1 ] > a[i] && dp[i][0 ] > dp[i - 1 ][0 ]) { dp[i][0 ] = dp[i - 1 ][0 ]; op[i][0 ] = 0 ; } if (dp[i - 1 ][1 ] > a[i] && dp[i][0 ] > a[i - 1 ]) { dp[i][0 ] = a[i - 1 ]; op[i][0 ] = 1 ; } } if (dp[n][1 ] != -inf) { printf ("YES\n" ); for (int i = n, optmp = 1 ; i >= 1 ; i--) { opt[i] = optmp; optmp = op[i][optmp]; } for (int i = 1 ; i <= n; i++) { printf ("%d " , opt[i] != 1 ); } } else if (dp[n][0 ] != inf) { printf ("YES\n" ); for (int i = n, optmp = 0 ; i >= 1 ; i--) { opt[i] = optmp; optmp = op[i][optmp]; } for (int i = 1 ; i <= n; i++) { printf ("%d " , opt[i] != 1 ); } } else printf ("NO" ); return 0 ; }