[SDOI2017]树点涂色

Posted colythme

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SDOI2017]树点涂色相关的知识,希望对你有一定的参考价值。

题意

有操作:

  • 1 $x$

把点 $x到根节点的路径上所有的点染上一种没有用过的新颜色。

  • 2 $x$ $y$

求 $x到 $y的路径的权值。

  • 3 $x$

在以 $x$ 为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。

题解

因为观察到一个颜色一定是一条向根节点的链,也就是说一条链代表了一个信息,那么就可以用 $LCT$ 中的一个 $Splay$ 去维护一条链(颜色)

那么一个节点的“权值”即为它到根节点经过的轻边个数,求出单点“权值”后,直接用差分即可解决操作 $2$

用树剖可以解决,但是这样的话连 $LCT$ 都不用了,同理,想到 $dfs$ 序,在 $Access$ 操作的时候删掉一条轻边并且增加一条轻边,答案有修改的只有该轻边端点包含的子树,那么直接线段树修改就好了

代码

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 
  5 #define lson root << 1
  6 #define rson root << 1 | 1
  7 
  8 using namespace std;
  9 
 10 const int MAXN = 1e05 + 10;
 11 const int MAXM = 1e05 + 10;
 12 
 13 struct LinkedForwardStar {
 14     int to;
 15 
 16     int next;
 17 } ;
 18 
 19 LinkedForwardStar Link[MAXM << 1];
 20 int Head[MAXN]= {0};
 21 int size = 0;
 22 
 23 void Insert (int u, int v) {
 24     Link[++ size].to = v;
 25     Link[size].next = Head[u];
 26 
 27     Head[u] = size;
 28 }
 29 
 30 const int Root = 1;
 31 
 32 int Deep[MAXN];
 33 int Size[MAXN]= {0};
 34 int Dfn[MAXN], Rank[MAXN];
 35 int dfsord = 0;
 36 
 37 int Maxv[MAXN << 2]= {0};
 38 int lazy[MAXN << 2]= {0};
 39 void pushdown (int root) {
 40     if (lazy[root]) {
 41         Maxv[lson] += lazy[root];
 42         Maxv[rson] += lazy[root];
 43         lazy[lson] += lazy[root];
 44         lazy[rson] += lazy[root];
 45         lazy[root] = 0;
 46     }
 47 }
 48 void Build (int root, int left, int right) {
 49     if (left == right) {
 50         Maxv[root] = Deep[Rank[left]];
 51         return ;
 52     }
 53     int mid = (left + right) >> 1;
 54     Build (lson, left, mid);
 55     Build (rson, mid + 1, right);
 56     Maxv[root] = max (Maxv[lson], Maxv[rson]);
 57 }
 58 void Modify (int root, int left, int right, int L, int R, int delta) {
 59     if (L <= left && right <= R) {
 60         Maxv[root] += delta;
 61         lazy[root] += delta;
 62         return ;
 63     }
 64     pushdown (root);
 65     int mid = (left + right) >> 1;
 66     if (L <= mid)
 67         Modify (lson, left, mid, L, R, delta);
 68     if (R >  mid)
 69         Modify (rson, mid + 1, right, L, R, delta);
 70     Maxv[root] = max (Maxv[lson], Maxv[rson]);
 71 }
 72 int Query (int root, int left, int right, int L, int R) {
 73     if (L <= left && right <= R)
 74         return Maxv[root];
 75     pushdown (root);
 76     int mid = (left + right) >> 1;
 77     int maxv = 0;
 78     if (L <= mid)
 79         maxv = max (maxv, Query (lson, left, mid, L, R));
 80     if (R > mid)
 81         maxv = max (maxv, Query (rson, mid + 1, right, L, R));
 82     return maxv;
 83 }
 84 
 85 int N, M;
 86 
 87 int father[MAXN]= {0};
 88 int son[MAXN][2]= {0};
 89 int isroot (int p) {
 90     return son[father[p]][0] != p && son[father[p]][1] != p;
 91 }
 92 int sonbel (int p) {
 93     return son[father[p]][1] == p;
 94 }
 95 void rotate (int p) {
 96     int fa = father[p], anc = father[fa];
 97     int s = sonbel (p);
 98     son[fa][s] = son[p][s ^ 1];
 99     if (son[fa][s])
100         father[son[fa][s]] = fa;
101     if (! isroot (fa))
102         son[anc][sonbel (fa)] = p;
103     father[p] = anc;
104     son[p][s ^ 1] = fa, father[fa] = p;
105 }
106 void splay (int p) {
107     for (int fa = father[p]; ! isroot (p); rotate (p), fa = father[p])
108         if (! isroot (fa))
109             sonbel (p) == sonbel (fa) ? rotate (fa) : rotate (p);
110 }
111 int findroot (int p) {
112     while (son[p][0])
113         p = son[p][0];
114     return p;
115 }
116 void Access (int p) {
117     for (int tp = 0; p; tp = p, p = father[p]) {
118         splay (p);
119         if (son[p][1]) {
120             int rt = findroot (son[p][1]);
121             Modify (Root, 1, N, Dfn[rt], Dfn[rt] + Size[rt] - 1, 1);
122         }
123         son[p][1] = tp;
124         if (son[p][1]) {
125             int rt = findroot (son[p][1]);
126             Modify (Root, 1, N, Dfn[rt], Dfn[rt] + Size[rt] - 1, - 1);
127         }
128     }
129 }
130 
131 int ances[MAXN][20];
132 void DFS (int root, int fa) {
133     Dfn[root] = ++ dfsord, Rank[dfsord] = root;
134     ances[root][0] = father[root] = fa;
135     for (int j = 1; j <= 18; j ++) {
136         if (! ances[root][j - 1])
137             break;
138         ances[root][j] = ances[ances[root][j - 1]][j - 1];
139     }
140     Size[root] = 1;
141     for (int i = Head[root]; i; i = Link[i].next) {
142         int v = Link[i].to;
143         if (v == fa)
144             continue;
145         Deep[v] = Deep[root] + 1;
146         DFS (v, root);
147         Size[root] += Size[v];
148     }
149 }
150 
151 int LCA (int x, int y) {
152     if (Deep[x] < Deep[y])
153         swap (x, y);
154     int fx = x, fy = y;
155     for (int j = 18; j >= 0; j --)
156         if (Deep[ances[fx][j]] >= Deep[fy])
157             fx = ances[fx][j];
158     if (fx == fy)
159         return fy;
160     for (int j = 18; j >= 0; j --)
161         if (ances[fx][j] != ances[fy][j]) {
162             fx = ances[fx][j];
163             fy = ances[fy][j];
164         }
165     return ances[fx][0];
166 }
167 
168 int getnum () {
169     int num = 0;
170     char ch = getchar ();
171 
172     while (! isdigit (ch))
173         ch = getchar ();
174     while (isdigit (ch))
175         num = (num << 3) + (num << 1) + ch - 0, ch = getchar ();
176 
177     return num;
178 }
179 
180 int main () {
181     N = getnum (), M = getnum ();
182     for (int i = 1; i < N; i ++) {
183         int u = getnum (), v = getnum ();
184         Insert (u, v), Insert (v, u);
185     }
186     Deep[Root] = 1, DFS (Root, 0);
187     Build (Root, 1, N);
188     for (int i = 1; i <= M; i ++) {
189         int opt = getnum ();
190         if (opt == 1) {
191             int p = getnum ();
192             Access (p);
193         }
194         else if (opt == 2) {
195             int x = getnum (), y = getnum ();
196             int lca = LCA (x, y);
197             int qx = Query (Root, 1, N, Dfn[x], Dfn[x]);
198             int qy = Query (Root, 1, N, Dfn[y], Dfn[y]);
199             int qlca = Query (Root, 1, N, Dfn[lca], Dfn[lca]);
200             int ans = qx + qy - (qlca << 1) + 1;
201             printf ("%d
", ans);
202         }
203         else if (opt == 3) {
204             int p = getnum ();
205             int ans = Query (Root, 1, N, Dfn[p], Dfn[p] + Size[p] - 1);
206             printf ("%d
", ans);
207         }
208     }
209 
210     return 0;
211 }
212 
213 /*
214 5 6
215 1 2
216 2 3
217 3 4
218 3 5
219 2 4 5
220 3 3
221 1 4
222 2 4 5
223 1 5
224 2 4 5
225 */

 

以上是关于[SDOI2017]树点涂色的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 4817: [Sdoi2017]树点涂色

[Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)

bzoj4817: [Sdoi2017]树点涂色

bzoj4817 [Sdoi2017]树点涂色

Luogu3703 SDOI2017树点涂色

[BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)