某题目1 二叉搜索树 最长不下降子序列
Description
给你一棵二叉树,每个点有点权(整数),你可以改变某些点的点权(只能改成整数),使这棵树满足二叉搜索树的性质,求满足条件最少的修改的点的数目。
n <= 1e5
Solution
一看到二叉搜索树,就要做中序遍历,得到序列a
要使修改的点的数量最少,即保留的最多原来的点。
如果能把点权改成小数的话,这个就可以直接做最长上升子序列。
但现在点权只能改成整数,需要考虑空隙的问题。
我们不妨设bi = ai-i,可以发现问题就转化为最长不下降子序列。
为什么呢?
设aj和ai,且满足i > j,若i和j都保留,则必须满足ai-aj >= i-j,整理得ai-i >= aj-j
最长的可保留子序列即ai-i的最长不下降子序列。
Code
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <string> 5 #include <algorithm> 6 #include <stack> 7 8 using namespace std; 9 10 #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i) 11 #define mset(a, b) memset(a, b, sizeof(a)) 12 const int maxn = 1e5+10; 13 int n, a[maxn], b[maxn], b_cnt; 14 int t[maxn], t_cnt; 15 int ls[maxn], rs[maxn]; 16 int mx[maxn*4]; 17 18 void build_tree(int rt, int l, int r) 19 { 20 mx[rt] = 0; 21 if (l == r) return ; 22 int mid = (l+r)>>1; 23 build_tree(rt<<1, l, mid); 24 build_tree((rt<<1)+1, mid+1, r); 25 } 26 27 void pushup(int rt) { mx[rt] = max(mx[rt<<1], mx[(rt<<1)+1]); } 28 29 void modify(int rt, int l, int r, int p, int d) 30 { 31 if (l == r) { mx[rt] = max(mx[rt], d); return ; } 32 int mid = (l+r)>>1; 33 if (p <= mid) modify(rt<<1, l, mid, p, d); 34 else modify((rt<<1)+1, mid+1, r, p, d); 35 pushup(rt); 36 } 37 38 int query(int rt, int l, int r, int L, int R) 39 { 40 if (L <= l && r <= R) return mx[rt]; 41 int mid = (l+r)>>1, ret = 0; 42 if (L <= mid) ret = query(rt<<1, l, mid, L, R); 43 if (R > mid) ret = max(ret, query((rt<<1)+1, mid+1, r, L, R)); 44 return ret; 45 } 46 47 int f[maxn]; 48 stack <int> s; 49 bool vis[maxn]; 50 51 void bfs(int k) 52 { 53 s.push(k); 54 mset(vis, 0); 55 while (!s.empty()) 56 { 57 int u = s.top(); 58 if (ls[u] != -1 && !vis[ls[u]]) { s.push(ls[u]); continue ; } 59 vis[u] = true, b[++b_cnt] = a[u], b[b_cnt] -= b_cnt; s.pop(); 60 if (rs[u] != -1 && !vis[rs[u]]) { s.push(rs[u]); continue ; } 61 } 62 } 63 64 int main() 65 { 66 scanf("%d", &n); 67 t_cnt = 0; 68 REP(i, 1, n) scanf("%d", &a[i]); 69 mset(ls, -1), mset(rs, -1); 70 REP(i, 2, n) 71 { 72 int fa, ty; 73 scanf("%d %d", &fa, &ty); 74 (ty ? rs[fa] : ls[fa]) = i; 75 } 76 b_cnt = 0, bfs(1); 77 REP(i, 1, n) t[i] = b[i]; 78 sort(t+1, t+n+1); 79 t_cnt = 1; 80 REP(i, 2, n) 81 if (t[i] != t[i-1]) t[++t_cnt] = t[i]; 82 REP(i, 1, n) 83 b[i] = lower_bound(t+1, t+t_cnt+1, b[i])-t; 84 build_tree(1, 1, t_cnt); 85 REP(i, 1, n) 86 { 87 f[i] = query(1, 1, t_cnt, 1, b[i])+1; 88 modify(1, 1, t_cnt, b[i], f[i]); 89 } 90 printf("%d\n", n-mx[1]); 91 return 0; 92 }
Nothing is impossible!