洛谷P3703 树点涂色

题意:

解:

发现我们每次染的都是不同的颜色,那么用lct维护的话一个颜色就会在一个splay里。染色是access。

维护每个节点到根路径上的虚边数量。

虚边的切换只会在access和link中出现。于是access的时候顺便修改那个子树。lct上啥也不用维护。

查询链可以用两端点减去lca。

  1 #include <bits/stdc++.h>
  2 
  3 const int N = 100010, INF = 0x3f3f3f3f;
  4 
  5 struct Edge {
  6     int nex, v;
  7 }edge[N << 1]; int tp;
  8 
  9 int e[N], n, siz[N], pos[N], id[N], d[N], num, top[N], father[N], son[N]; /// tree
 10 int fa[N], s[N][2], stk[N], Top; /// lct
 11 bool rev[N];
 12 int large[N << 2], tag[N << 2]; /// seg
 13 
 14 inline void add(int x, int y) {
 15     tp++;
 16     edge[tp].v = y;
 17     edge[tp].nex = e[x];
 18     e[x] = tp;
 19     return;
 20 }
 21 
 22 void DFS_1(int x, int f) { /// father siz son d
 23     siz[x] = 1;
 24     fa[x] = father[x] = f;
 25     for(int i = e[x]; i; i = edge[i].nex) {
 26         int y = edge[i].v;
 27         if(y == f) continue;
 28         d[y] = d[x] + 1;
 29         DFS_1(y, x);
 30         siz[x] += siz[y];
 31         if(siz[y] > siz[son[x]]) {
 32             son[x] = y;
 33         }
 34     }
 35     return;
 36 }
 37 
 38 void DFS_2(int x, int f) { /// top id pos
 39     top[x] = f;
 40     pos[x] = ++num;
 41     id[num] = x;
 42     if(son[x]) DFS_2(son[x], f);
 43     for(int i = e[x]; i; i = edge[i].nex) {
 44         int y = edge[i].v;
 45         if(y == father[x] || y == son[x]) continue;
 46         DFS_2(y, y);
 47     }
 48     return;
 49 }
 50 
 51 inline void Pushdown(int o) {
 52     if(tag[o]) {
 53         int ls = o << 1, rs = o << 1 | 1;
 54         tag[ls] += tag[o];
 55         tag[rs] += tag[o];
 56         large[ls] += tag[o];
 57         large[rs] += tag[o];
 58         tag[o] = 0;
 59     }
 60     return;
 61 }
 62 
 63 void build(int l, int r, int o) {
 64     if(l == r) {
 65         large[o] = d[id[r]];
 66         return;
 67     }
 68     int mid = (l + r) >> 1;
 69     build(l, mid, o << 1);
 70     build(mid + 1, r, o << 1 | 1);
 71     large[o] = std::max(large[o << 1], large[o << 1 | 1]);
 72     return;
 73 }
 74 
 75 void add(int L, int R, int v, int l, int r, int o) {
 76     if(L <= l && r <= R) {
 77         large[o] += v;
 78         tag[o] += v;
 79         return;
 80     }
 81     Pushdown(o);
 82     int mid = (l + r) >> 1;
 83     if(L <= mid) add(L, R, v, l, mid, o << 1);
 84     if(mid < R) add(L, R, v, mid + 1, r, o << 1 | 1);
 85     large[o] = std::max(large[o << 1], large[o << 1 | 1]);
 86     return;
 87 }
 88 
 89 int getMax(int L, int R, int l, int r, int o) {
 90     if(L <= l && r <= R) return large[o];
 91     int mid = (l + r) >> 1, ans = -INF;
 92     Pushdown(o);
 93     if(L <= mid) ans = std::max(ans, getMax(L, R, l, mid, o << 1));
 94     if(mid < R) ans = std::max(ans, getMax(L, R, mid + 1, r, o << 1 | 1));
 95     return ans;
 96 }
 97 
 98 int ask(int p, int l, int r, int o) {
 99     if(l == r) return large[o];
100     Pushdown(o);
101     int mid = (l + r) >> 1;
102     if(p <= mid) return ask(p, l, mid, o << 1);
103     else return ask(p, mid + 1, r, o << 1 | 1);
104 }
105 
106 inline void pushdown(int x) {
107     if(rev[x]) {
108         std::swap(s[x][0], s[x][1]);
109         if(s[x][0]) rev[s[x][0]] ^= 1;
110         if(s[x][1]) rev[s[x][1]] ^= 1;
111         rev[x] = 0;
112     }
113     return;
114 }
115 
116 inline void pushup(int x) {
117     return;
118 }
119 
120 inline bool no_root(int x) {
121     return (s[fa[x]][0] == x) || (s[fa[x]][1] == x);
122 }
123 
124 inline void rotate(int x) {
125     int y = fa[x];
126     int z = fa[y];
127     bool f = (s[y][1] == x);
128 
129     fa[x] = z;
130     if(no_root(y)) {
131         s[z][s[z][1] == y] = x;
132     }
133     s[y][f] = s[x][!f];
134     if(s[x][!f]) {
135         fa[s[x][!f]] = y;
136     }
137     s[x][!f] = y;
138     fa[y] = x;
139 
140     pushup(y);
141     return;
142 }
143 
144 inline void splay(int x) {
145     int y = x;
146     stk[++Top] = y;
147     while(no_root(y)) {
148         y = fa[y];
149         stk[++Top] = y;
150     }
151     while(Top) {
152         pushdown(stk[Top]);
153         Top--;
154     }
155 
156     y = fa[x];
157     int z = fa[y];
158     while(no_root(x)) {
159         if(no_root(y)) {
160             (s[z][1] == y) ^ (s[y][1] == x) ?
161             rotate(x) : rotate(y);
162         }
163         rotate(x);
164         y = fa[x];
165         z = fa[y];
166     }
167     pushup(x);
168     return;
169 }
170 
171 inline void change(int x, int v) {
172     pushdown(x);
173     while(s[x][0]) {
174         x = s[x][0];
175         pushdown(x);
176     }
177     /// x
178     add(pos[x], pos[x] + siz[x] - 1, v, 1, n, 1);
179     return;
180 }
181 
182 inline void access(int x) {
183     int y = 0;
184     while(x) {
185         splay(x);
186         if(s[x][1]) change(s[x][1], 1);
187         if(y) change(y, -1);
188         s[x][1] = y;
189         pushup(x);
190         y = x;
191         x = fa[x];
192     }
193     return;
194 }
195 
196 inline int lca(int x, int y) {
197     while(top[x] != top[y]) {
198         if(d[top[x]] < d[top[y]]) {
199             y = father[top[y]];
200         }
201         else {
202             x = father[top[x]];
203         }
204     }
205     return d[x] < d[y] ? x : y;
206 }
207 
208 inline int ask(int x, int y) {
209     //printf("ask : %d %d lca %d \n", x, y, lca(x, y));
210     //printf("ask : %d + %d - 2 * %d \n", ask(pos[x], 1, n, 1), ask(pos[y], 1, n, 1), ask(pos[lca(x, y)], 1, n, 1));
211     return ask(pos[x], 1, n, 1) + ask(pos[y], 1, n, 1) - 2 * ask(pos[lca(x, y)], 1, n, 1);
212 }
213 
214 inline int query(int x) {
215     return getMax(pos[x], pos[x] + siz[x] - 1, 1, n, 1);
216 }
217 
218 int main() {
219     int m;
220     scanf("%d%d", &n, &m);
221     for(int i = 1, x, y; i < n; i++) {
222         scanf("%d%d", &x, &y);
223         add(x, y); add(y, x);
224     }
225     /// init
226     DFS_1(1, 0);
227     DFS_2(1, 1);
228     build(1, n, 1);
229 
230     for(int i = 1, f, x, y; i <= m; i++) {
231         scanf("%d%d", &f, &x);
232         if(f == 1) { /// change
233             access(x);
234         }
235         else if(f == 2) {
236             scanf("%d", &y);
237             printf("%d\n", ask(x, y) + 1);
238         }
239         else { /// f == 3
240             printf("%d\n", query(x) + 1);
241         }
242     }
243     return 0;
244 }
AC代码

 

posted @ 2019-03-06 13:39  huyufeifei  阅读(169)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜