[HNOI2014]世界树

· 题解

  参考hzwer

  首先看到Mi的条件想到构造虚树。

  虚树中的一条边已经覆盖了整个出现在这条边上的点的子树的情况。

  那么只需倍增查找所属议事处有变化的边界节点,同时计算这两段节点的贡献即可。

· 代码

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <vector>
  5 #include <algorithm>
  6 
  7 using namespace std;
  8 
  9 const int MAXN = 3e05 + 10;
 10 const int MAXM = 3e05 + 10;
 11 
 12 struct LinkedForwardStar {
 13     int to;
 14     
 15     int next;
 16 } ;
 17 
 18 LinkedForwardStar Link[MAXM << 1];
 19 int Head[MAXN]= {0};
 20 int size = 0;
 21 
 22 void Insert (int u, int v) {
 23     Link[++ size].to = v;
 24     Link[size].next = Head[u];
 25     
 26     Head[u] = size;
 27 }
 28 
 29 const int Root = 1;
 30 
 31 int Deep[MAXN];
 32 
 33 int Size[MAXN];
 34 
 35 int Dfn[MAXN];
 36 int dfsord = 0;
 37 
 38 int Father[MAXN][23];
 39 
 40 void DFS (int root, int father) {
 41     Dfn[root] = ++ dfsord;
 42     Size[root] = 1;
 43     Father[root][0] = father;
 44     for (int j = 1; j <= 20; j ++) {
 45         if (! Father[root][j - 1])
 46             continue;
 47         
 48         Father[root][j] = Father[Father[root][j - 1]][j - 1];
 49     }
 50     
 51     for (int i = Head[root]; i; i = Link[i].next) {
 52         int v = Link[i].to;
 53         
 54         if (v == father)
 55             continue;
 56         
 57         Deep[v] = Deep[root] + 1;
 58         
 59         DFS (v, root);
 60         
 61         Size[root] += Size[v];
 62     }
 63 }
 64 
 65 int LCA (int x, int y) {
 66     if (Deep[x] < Deep[y])
 67         swap (x, y);
 68     
 69     int fx = x, fy = y;
 70     for (int j = 20; j >= 0; j --)
 71         if (Deep[Father[fx][j]] >= Deep[fy])
 72             fx = Father[fx][j];
 73     
 74     if (fx == fy)
 75         return fy;
 76     
 77     for (int j = 20; j >= 0; j --)
 78         if (Father[fx][j] != Father[fy][j]) {
 79             fx = Father[fx][j];
 80             fy = Father[fy][j];
 81         }
 82     
 83     return Father[fx][0];
 84 }
 85 
 86 int Dist (int x, int y) {
 87     int lca = LCA (x, y);
 88     return Deep[x] + Deep[y] - 2 * Deep[lca];
 89 }
 90 
 91 int N, Q;
 92 
 93 int A[MAXN];
 94 
 95 vector<int> Graph[MAXN];
 96 
 97 int Stack[MAXN];
 98 int top = 0;
 99 
100 int Belong[MAXN]= {0};
101 
102 bool comp (const int& a, const int& b) {
103     return Dfn[a] < Dfn[b];
104 }
105 
106 void Insert_IvTree (int p) {
107     if (! top) {
108         Stack[++ top] = p;
109         
110         return ;
111     }
112     
113     int lca = 0;
114     while (top > 0) {
115         lca = LCA (Stack[top], p);
116         if (top > 1 && Deep[lca] < Deep[Stack[top - 1]])
117             Graph[Stack[top - 1]].push_back(Stack[top]), top --;
118         else if (Deep[lca] < Deep[Stack[top]]) {
119             Graph[lca].push_back(Stack[top]), top --;
120             break;
121         }
122         else
123             break;
124     }
125     
126     if (Stack[top] != lca)
127         Stack[++ top] = lca;
128     Stack[++ top] = p;
129 }
130 
131 int M;
132 
133 void Construct () {
134     top = 0;
135     if (Belong[Root] != Root)
136         Stack[++ top] = Root;
137     
138     sort (A + 1, A + M + 1, comp);
139     
140     for (int i = 1; i <= M; i ++)
141         Insert_IvTree (A[i]);
142     while (top > 1)
143         Graph[Stack[top - 1]].push_back(Stack[top]), top --;
144 }
145 
146 int Rank[MAXN]= {0};
147 
148 int Rest[MAXN]= {0};
149 
150 void Get_BelSon (int root) {
151     Rank[++ dfsord] = root;
152     Rest[root] = Size[root];
153     
154     for (int i = 0; i < Graph[root].size(); i ++) {
155         int v = Graph[root][i];
156         
157         Get_BelSon (v);
158         
159         if (! Belong[v])
160             continue;
161         
162         int dist1 = Dist (Belong[root], root), dist2 = Dist (Belong[v], root);
163         if (! Belong[root] || dist1 > dist2 || (dist1 == dist2 && Belong[root] > Belong[v]))
164             Belong[root] = Belong[v];
165     }
166 }
167 
168 void Get_BelFat (int root) {
169     for (int i = 0; i < Graph[root].size(); i ++) {
170         int v = Graph[root][i];
171         
172         int dist1 = Dist (Belong[root], v), dist2 = Dist (Belong[v], v);
173         if (! Belong[v] || dist1 < dist2 || (dist1 == dist2 && Belong[root] < Belong[v]))
174             Belong[v] = Belong[root];
175         
176         Get_BelFat (v);
177     }
178 }
179 
180 int Count[MAXN]= {0};
181 
182 void Calc (int u, int v) {
183     int p = v;
184     for (int j = 20; j >= 0; j --)
185         if (Deep[Father[p][j]] > Deep[u])
186             p = Father[p][j];
187     
188     Rest[u] -= Size[p];
189     
190     if (Belong[u] == Belong[v]) {
191         Count[Belong[u]] += Size[p] - Size[v];
192         return ;
193     }
194     
195     int mid = v;
196     for (int j = 20; j >= 0; j --) {
197         if (Deep[Father[mid][j]] <= Deep[u])
198             continue;
199         
200         int nextpos = Father[mid][j];
201         int dist1 = Dist (Belong[v], nextpos), dist2 = Dist (Belong[u], nextpos);
202         if (dist1 < dist2 || (dist1 == dist2 && Belong[v] < Belong[u]))
203             mid = nextpos;
204     }
205     
206     Count[Belong[u]] += Size[p] - Size[mid];
207     Count[Belong[v]] += Size[mid] - Size[v];
208 }
209 
210 int getnum () {
211     int num = 0;
212     char ch = getchar ();
213     
214     while (! isdigit (ch))
215         ch = getchar ();
216     while (isdigit (ch))
217         num = num * 10 + ch - '0', ch = getchar ();
218     
219     return num;
220 }
221 
222 int Orig[MAXN];
223 
224 void Solve () {
225     M = getnum ();
226     
227     for (int i = 1; i <= M; i ++)
228         A[i] = Orig[i] = getnum ();
229     
230     for (int i = 1; i <= M; i ++)
231         Belong[A[i]] = A[i];
232     
233     Construct ();
234     
235     dfsord = 0;
236     Get_BelSon (Root), Get_BelFat (Root);
237     
238     for (int i = 1; i <= dfsord; i ++) {
239         int u = Rank[i];
240         for (int j = 0; j < Graph[u].size(); j ++) {
241             int v = Graph[u][j];
242             Calc (u, v);
243         }
244     }
245     
246     for (int i = 1; i <= dfsord; i ++)
247         Count[Belong[Rank[i]]] += Rest[Rank[i]];
248     
249     for (int i = 1; i <= M; i ++) {
250         if (i > 1)
251             putchar (' ');
252         printf ("%d", Count[Orig[i]]);
253     }
254     puts ("");
255     
256     for (int i = 1; i <= dfsord; i ++) {
257         Graph[Rank[i]].clear();
258         Count[Rank[i]] = Belong[Rank[i]] = Rest[Rank[i]] = 0;
259     }
260 }
261 
262 int main () {
263     N = getnum ();
264     
265     for (int i = 1; i < N; i ++) {
266         int u, v;
267         u = getnum (), v = getnum ();
268         
269         Insert (u, v), Insert (v, u);
270     }
271     
272     Deep[Root] = 1;
273     DFS (Root, 0);
274     
275     Q = getnum ();
276     
277     for (int Case = 1; Case <= Q; Case ++)
278         Solve ();
279     
280     return 0;
281 }
282 
283 /*
284 10
285 2 1
286 3 2
287 4 3
288 5 4
289 6 1
290 7 3
291 8 3
292 9 4
293 10 1
294 5
295 2
296 6 1
297 5
298 2 7 3 6 9
299 1
300 8
301 4
302 8 7 10 3
303 5
304 2 9 3 5 8
305 */
View Code
原文地址:https://www.cnblogs.com/Colythme/p/9745928.html