BZOJ3553 [Shoi2014]三叉神经树

容易想到树链剖分来维护

一条链上维护儿子中是1的个数为1的点的最长值和儿子是1的个数为2的点的最长值

于是每次修改的时候就二分查询会更新到哪里,再直接链修改就好了

单次查询复杂度$O(logn^2)$,单次修改复杂度为$O(logn)$

注意如果动态开点太多会导致MLE,最后解决办法是在每个线段树节点上增加了一个res变量表示返回值

  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
", 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 }
View Code

(p.s. 论编程能力弱的后果。。。写了一下午,调了一晚上QAQQQ)

By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
原文地址:https://www.cnblogs.com/rausen/p/4464328.html