BZOJ 4551: [Tjoi2016&Heoi2016]树
4551: [Tjoi2016&Heoi2016]树
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 941 Solved: 485
[Submit][Status][Discuss]
Description
在2016年,佳媛姐姐刚刚学习了树,非常开心。现在他想解决这样一个问题:给定一颗有根树(根为1),有以下
两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均无标记,而且对于某个
结点,可以打多次标记。)2. 询问操作:询问某个结点最近的一个打了标记的祖先(这个结点本身也算自己的祖
先)你能帮帮他吗?
Input
输入第一行两个正整数N和Q分别表示节点个数和操作次数接下来N-1行,每行两个正整数u,v(1≤u,v≤n)表示u到v
有一条有向边接下来Q行,形如“opernum”oper为“C”时表示这是一个标记操作,oper为“Q”时表示这是一个询
问操作对于每次询问操作,1 ≤ N, Q ≤ 100000。
Output
输出一个正整数,表示结果
Sample Input
5 5
1 2
1 3
2 4
2 5
Q 2
C 2
Q 2
Q 5
Q 3
1 2
1 3
2 4
2 5
Q 2
C 2
Q 2
Q 5
Q 3
Sample Output
1
2
2
1
2
2
1
HINT
新加数据9组(By HFLSyzx ),未重测--2016.8.2
Source
离线,用并查集维护答案指向。
1 #include <cstdio> 2 3 const int mxn = 200005; 4 5 int n, m; 6 7 int tot; 8 int hd[mxn]; 9 int to[mxn]; 10 int nt[mxn]; 11 12 inline void add(int x, int y) 13 { 14 nt[++tot] = hd[x], to[tot] = y, hd[x] = tot; 15 nt[++tot] = hd[y], to[tot] = x, hd[y] = tot; 16 } 17 18 int cnt[mxn]; 19 int fat[mxn]; 20 int pre[mxn]; 21 22 inline int find(int u) 23 { 24 static int stk[mxn], top; 25 26 while (u != fat[u]) 27 stk[++top] = u, u = fat[u]; 28 29 while (top) 30 fat[stk[top--]] = u; 31 32 return u; 33 } 34 35 int opt[mxn]; 36 int num[mxn]; 37 int ans[mxn]; 38 39 void preDFS(int u, int f) 40 { 41 pre[u] = f; 42 43 if (!cnt[u]) 44 fat[u] = find(f); 45 46 for (int i = hd[u]; i; i = nt[i]) 47 if (to[i] != f)preDFS(to[i], u); 48 } 49 50 signed main(void) 51 { 52 // freopen("tree.in", "r", stdin); 53 // freopen("tree.out", "w", stdout); 54 55 scanf("%d%d", &n, &m); 56 57 for (int i = 1, x, y; i < n; ++i) 58 scanf("%d%d", &x, &y), add(x, y); 59 60 ++cnt[1]; 61 62 for (int i = 1; i <= m; ++i) 63 { 64 static char s[5]; 65 scanf("%s%d", s, num + i); 66 67 if (s[0] == 'C') 68 opt[i] = 1, ++cnt[num[i]]; 69 } 70 71 for (int i = 1; i <= n; ++i) 72 fat[i] = i; 73 74 preDFS(1, 0); 75 76 for (int i = m; i >= 1; --i) 77 { 78 if (opt[i] == 0) 79 ans[i] = find(num[i]); 80 else if (--cnt[num[i]] == 0) 81 fat[num[i]] = find(pre[num[i]]); 82 } 83 84 for (int i = 1; i <= m; ++i) 85 if (opt[i] == 0) 86 printf("%d\n", ans[i]); 87 88 fclose(stdin); 89 fclose(stdout); 90 }
@Author: YouSiki