CodeForces 379F 树的直径 New Year Tree

题意:每次操作新加两个叶子节点,每次操作完以后询问树的直径。

维护树的直径的两个端点U,V,每次计算一下新加进来的叶子节点到U,V两点的距离,如果有更长的就更新。

因为根据树的直径的求法,若出现新的直径,一定是到U或者到V距离最远。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 
 6 const int maxn = 1000000 + 1000;
 7 const int logmaxn = 20;
 8 
 9 int n, Q;
10 
11 int L[maxn];
12 int fa[maxn];
13 int anc[maxn][logmaxn];
14 
15 void add(int u, int pa)
16 {
17     fa[u] = pa;
18     L[u] = L[pa] + 1;
19     anc[u][0] = pa;
20     for(int j = 1; (1 << j) < n; j++) if(anc[u][j-1])
21         anc[u][j] = anc[anc[u][j-1]][j-1];
22 }
23 
24 int LCA(int p, int q)
25 {
26     if(L[p] < L[q]) std::swap(p, q);
27     int log;
28     for(log = 1; (1 << log) <= L[p]; log++); log--;
29     for(int i = log; i >= 0; i--)
30         if(L[p] - (1 << i) >= L[q]) p = anc[p][i];
31     if(p == q) return p;
32     for(int i = log; i >= 0; i--)
33         if(anc[p][i] && anc[p][i] != anc[q][i])
34             p = anc[p][i], q = anc[q][i];
35     return fa[p];
36 }
37 
38 int distance(int u, int v)
39 {
40     int l = LCA(u, v);
41     return L[u] + L[v] - L[l] * 2;
42 }
43 
44 int main()
45 {
46     scanf("%d", &Q);
47     n = 4;
48     fa[2] = fa[3] = fa[4] = 1;
49     L[2] = L[3] = L[4] = 1;
50     anc[2][0] = anc[3][0] = anc[4][0] = 1;
51 
52     int U = 2, V = 3, diameter = 2;
53     while(Q--)
54     {
55         int p; scanf("%d", &p);
56         add(++n, p);
57         add(++n, p);
58         int l1 = distance(n, U), l2 = distance(n, V);
59         if(l1 >= l2 && l1 >= diameter)
60         {
61             V = n;
62             diameter = l1;
63         }
64         else if(l2 >= l1 && l2 >= diameter)
65         {
66             U = n;
67             diameter = l2;
68         }
69         printf("%d\n", diameter);
70     }
71 
72     return 0;
73 }
代码君

 

posted @ 2015-08-17 12:39  AOQNRMGYXLMV  阅读(229)  评论(0编辑  收藏  举报