题意: 给出一个序列,问每个位置的元素,分别属于哪一类的东西。第一类 没有出现在任何的上升子序列中。 第三类 出现在所有上升子序列中 。第二类 就是剩下的了。。
求两个东西 , dp[i] 表示 从1到 i 最长上升子序列的长度,dp1[i]表示从i到n 最长上升子序列的长度。
设原序列最长上升子序列长度为len
1. 若dp[i]+dp1[i] - 1 != len , 他就属于第一类。
2. 若 t = dp[i] 的 t 出现了不止一次,且不属于第一类,那他就是第二类。
剩下的就是第三类了。
代码写的有点戳。
#include<iostream> #include<cstdio> #include<cstring> #include<map> #include<vector> #include<stdlib.h> using namespace std; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 const int maxn = 111111; vector<int> q[maxn]; int erfen(int a[], int l, int r, int key) { int ans = -1; while (l <= r){ int mid = (l + r) >> 1; if (a[mid] >= key){ ans = mid; } if (a[mid] >= key) r = mid - 1; else l = mid + 1; } return ans; } int erfen1(int a[], int l, int r, int key) { int ans = -1; while (l <= r){ int mid = (l + r) >> 1; if (a[mid] <= key){ ans = mid; } if (a[mid] <= key) r = mid - 1; else l = mid + 1; } return ans; } int a[maxn], a1[maxn]; int ans[maxn], ans1[maxn]; int dp[maxn], dp1[maxn]; int vis[maxn]; int main() { int n; memset(vis, 0, sizeof(vis)); int cnt = 0; int cnt1 = 0; scanf("%d", &n); for (int i = 0; i<n; i++) scanf("%d", &a[i]); ans[cnt++] = a[0]; dp[0] = 1; for (int i = 1; i<n; i++){ int t = erfen(ans, 0, cnt - 1, a[i]); if (t == -1){ ans[cnt++] = a[i]; dp[i] = cnt; } else{ ans[t] = a[i]; dp[i] = t + 1; } } for (int i = 0; i<n; i++){ a1[i] = a[n - i - 1]; } cnt1 = 0; ans1[cnt1++] = a1[0]; dp1[0] = 1; for (int i = 1; i<n; i++){ int t = erfen1(ans1, 0, cnt1 - 1, a1[i]); if (t == -1){ ans1[cnt1++] = a1[i]; dp1[i] = cnt1; } else{ ans1[t] = a1[i]; dp1[i] = t + 1; } } for (int i = 0; i<n / 2; i++) swap(dp1[i], dp1[n - i - 1]); for (int i = 0; i<n; i++){ int t = dp[i] + dp1[i] - 1; if (t != cnt) vis[i] = 1; } for (int i = 0; i<n; i++){ if (vis[i]) continue; q[dp[i]].push_back(i); } for (int i = 0; i<n; i++){ int len = q[i].size(); if (len <= 1) continue; for (int j = 0; j<len; j++){ int t = q[i][j]; vis[t] = 2; } } for (int i = 0; i<n; i++){ if (!vis[i]) printf("3"); else printf("%d", vis[i]); } cout << endl; return 0; }
时间: 2024-10-26 13:59:45