感觉是个垃圾题啊, 为什么过的人这么少。。
dp[ i ][ 0 ]表示处理完前 i 个, 第 i 个是递增序列序列里的元素,递减序列的最大值。
dp[ i ][ 1 ]表示处理完前 i 个, 第 i 个是递减序列序列里的元素,递增序列的最小值。
然后随便转移转移顺便记录一下路径就好啦。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ull unsigned long long using namespace std; const int N = 2e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1000000007; const double eps = 1e-6; const double PI = acos(-1); int n, a[N], ans[N]; int dp[N][2], path[N][2]; int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i <= n; i++) dp[i][0] = -inf, dp[i][1] = inf; dp[1][0] = 1e9 + 1; dp[1][1] = -1; for(int i = 1; i < n; i++) { if(dp[i][0] > -inf) { if(a[i + 1] > a[i]) { if(dp[i][0] > dp[i + 1][0]) { dp[i + 1][0] = dp[i][0]; path[i + 1][0] = 0; } } if(a[i + 1] < dp[i][0]) { if(a[i] < dp[i + 1][1]) { dp[i + 1][1] = a[i]; path[i + 1][1] = 0; } } } if(dp[i][1] < inf) { if(a[i + 1] < a[i]) { if(dp[i][1] < dp[i + 1][1]) { dp[i + 1][1] = dp[i][1]; path[i + 1][1] = 1; } } if(a[i + 1] > dp[i][1]) { if(a[i] > dp[i + 1][0]) { dp[i + 1][0] = a[i]; path[i + 1][0] = 1; } } } } if(dp[n][0] > -inf) { puts("YES"); int now = 0; for(int i = n; i >= 1; i--) { ans[i] = now; now = path[i][now]; } for(int i = 1; i <= n; i++) printf("%d ", ans[i]); puts(""); } else if(dp[n][1] < inf) { puts("YES"); int now = 1; for(int i = n; i >= 1; i--) { ans[i] = now; now = path[i][now]; } for(int i = 1; i <= n; i++) printf("%d ", ans[i]); puts(""); } else { puts("NO"); } return 0; } /* */