BZOJ 4551: [Tjoi2016&Heoi2016]树

4551: [Tjoi2016&Heoi2016]树

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output

1
2
2
1

HINT

 

 新加数据9组(By HFLSyzx ),未重测--2016.8.2

 

Source

 
[Submit][Status][Discuss]

 

离线,用并查集维护答案指向。

 

 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

 

posted @ 2017-02-25 21:46  YouSiki  阅读(196)  评论(0编辑  收藏  举报