容易想到树链剖分来维护
一条链上维护儿子中是1的个数为1的点的最长值和儿子是1的个数为2的点的最长值
于是每次修改的时候就二分查询会更新到哪里,再直接链修改就好了
单次查询复杂度$O(logn^2)$,单次修改复杂度为$O(logn)$
注意如果动态开点太多会导致MLE,最后解决办法是在每个线段树节点上增加了一个res变量表示返回值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /************************************************************** 2 Problem: 3553 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:18880 ms 7 Memory:102672 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 12 using namespace std; 13 const int N = 5e5 + 5; 14 15 inline int read(); 16 17 int n; 18 int seq[N * 3]; 19 20 struct tree_node { 21 int v, dep, sz; 22 int son[3], fa, top, w; 23 } tr[N * 3]; 24 25 struct seg { 26 seg *ls, *rs, *res; 27 int tag, mx[2], sz; 28 29 #define Len (1 << 16) 30 inline void* operator new (size_t) { 31 static seg *mempool, *c; 32 if (c == mempool) 33 mempool = (c = new seg[Len]) + Len; 34 c -> ls = c -> rs = c -> res = NULL; 35 c -> tag = -1, c -> sz = 1, c -> mx[0] = c -> mx[1] = 0; 36 return c++; 37 } 38 #undef Len 39 40 inline void fill(int x) { 41 tag = x; 42 mx[0] = mx[1] = 0; 43 if (tag == 1) mx[0] = sz; 44 if (tag == 2) mx[1] = sz; 45 } 46 inline void push() { 47 if (tag != -1) { 48 if (ls) ls -> fill(tag); 49 if (rs) rs -> fill(tag); 50 tag = -1; 51 } 52 } 53 inline void update(seg *t1, seg *t2) { 54 sz = t1 -> sz + t2 -> sz; 55 mx[0] = t2 -> mx[0] + (t2 -> mx[0] == t2 -> sz ? t1 -> mx[0] : 0); 56 mx[1] = t2 -> mx[1] + (t2 -> mx[1] == t2 -> sz ? t1 -> mx[1] : 0); 57 } 58 59 #define mid (l + r >> 1) 60 void build(int l, int r) { 61 if (l == r) { 62 fill(tr[seq[l]].v); 63 return; 64 } 65 ls = new()seg, rs = new()seg, res = new()seg; 66 ls -> build(l, mid), rs -> build(mid + 1, r); 67 update(ls, rs); 68 } 69 70 void modify(int l, int r, int L, int R, int d) { 71 if (L <= l && r <= R) { 72 fill(d); 73 return; 74 } 75 push(); 76 if (L <= mid) ls -> modify(l, mid, L, R, d); 77 if (mid < R) rs -> modify(mid + 1, r, L, R, d); 78 update(ls, rs); 79 } 80 81 int query(int l, int r, int pos) { 82 if (l == r) return tag; 83 push(); 84 if (pos <= mid) return ls -> query(l, mid, pos); 85 else return rs -> query(mid + 1, r, pos); 86 } 87 seg* query(int l, int r, int L, int R) { 88 if (L <= l && r <= R) return this; 89 push(); 90 if (R <= mid) return ls -> query(l, mid, L, R); 91 if (mid < L) return rs -> query(mid + 1, r, L, R); 92 res -> update(ls -> query(l, mid, L, R), rs -> query(mid + 1, r, L, R)); 93 return res; 94 } 95 #undef mid 96 } *T; 97 98 inline void modify(int p, int tar, int c) { 99 while (tr[p].top != tr[tar].top) 100 T -> modify(1, n, tr[tr[p].top].w, tr[p].w, c), p = tr[tr[p].top].fa; 101 T -> modify(1, n, tr[tar].w, tr[p].w, c); 102 } 103 104 int change(int p) { 105 static int c, now, q; 106 static seg *tmp; 107 c = tr[p].v, now = tr[p].fa, tr[p].v = 1 - tr[p].v; 108 while (1) { 109 tmp = T -> query(1, n, tr[tr[now].top].w, tr[now].w); 110 if (tmp -> sz != tmp -> mx[c]) break; 111 now = tr[now].top; 112 if (!tr[now].fa || T -> query(1, n, tr[tr[now].fa].w) != c + 1) break; 113 now = tr[now].fa; 114 } 115 if (T -> query(1, n, tr[now].w) != c + 1) { 116 T -> modify(1, n, tr[now].w, tr[now].w, T -> query(1, n, tr[now].w) + (c ? -1 : 1)); 117 return T -> query(1, n, 1) >= 2; 118 } 119 if (now == tr[now].top) q = now; 120 else q = seq[tr[now].w - T -> query(1, n, tr[tr[now].top].w, tr[now].w) -> mx[c] + 1]; 121 modify(tr[p].fa, q, tr[p].v + 1); 122 if (tr[q].fa) T -> modify(1, n, tr[tr[q].fa].w, tr[tr[q].fa].w, T -> query(1, n, tr[tr[q].fa].w) + (c ? -1 : 1)); 123 return T -> query(1, n, 1) >= 2; 124 } 125 126 void get_seq() { 127 static int i, j, q[N], tot_q, tot_d, p, S; 128 q[tot_q = 1] = 1, tr[1].fa = 0; 129 for (i = 1; i <= n; ++i) 130 for (j = 0; j < 3; ++j) 131 if (tr[q[i]].son[j] <= n) 132 tr[q[++tot_q] = tr[q[i]].son[j]].dep = tr[q[i]].dep + 1; 133 for (i = 1; i <= n; ++i) tr[i].top = i, tr[i].sz = 1; 134 for (i = n; i; --i) tr[tr[q[i]].fa].sz += tr[q[i]].sz; 135 136 tr[0].sz = 0, tr[1].w = 1; 137 for (i = 1; i <= n; ++i) { 138 p = q[i], tot_d = tr[p].w; 139 for (j = S = 0; j < 3; ++j) 140 if (tr[p].son[j] <= n && tr[tr[p].son[j]].sz > tr[S].sz) 141 S = tr[p].son[j]; 142 if (S) 143 tr[S].w = tot_d + 1, tot_d += tr[S].sz, tr[S].top = tr[p].top; 144 for (j = 0; j < 3; ++j) 145 if (tr[p].son[j] <= n && tr[p].son[j] != S) 146 tr[tr[p].son[j]].w = tot_d + 1, tot_d += tr[tr[p].son[j]].sz; 147 } 148 for (i = n; i; --i) if (tr[q[i]].v >= 2) ++tr[tr[q[i]].fa].v; 149 for (i = 1; i <= n; ++i) seq[tr[i].w] = i; 150 } 151 152 int main() { 153 int i, j, Q; 154 n = read(); 155 for (i = 1; i <= n; ++i) 156 for (j = 0; j < 3; ++j) 157 tr[tr[i].son[j] = read()].fa = i; 158 for (i = n + 1; i <= 3 * n + 1; ++i) 159 tr[tr[i].fa].v += (tr[i].v = read()); 160 get_seq(); 161 T = new()seg, T -> build(1, n); 162 Q = read(); 163 while (Q--) 164 printf("%d\n", change(read())); 165 return 0; 166 } 167 168 inline int read() { 169 static int x; 170 static char ch; 171 x = 0, ch = getchar(); 172 while (ch < '0' || '9' < ch) 173 ch = getchar(); 174 while ('0' <= ch && ch <= '9') { 175 x = x * 10 + ch - '0'; 176 ch = getchar(); 177 } 178 return x; 179 }
(p.s. 论编程能力弱的后果。。。写了一下午,调了一晚上QAQQQ)
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen