bzoj4551 [Tjoi2016&Heoi2016]树

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

正解:并查集。

考虑离线倒序处理,先把标记结点和它的子树合并,然后处理询问时查询就输出值就好,打标记的话就是要把当前标记去掉,那么只要当前这个点没有标记了就把它和它父亲合并。

 

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <queue>
10 #include <stack>
11 #include <map>
12 #include <set>
13 #define inf (1<<30)
14 #define il inline
15 #define RG register
16 #define ll long long
17   
18 using namespace std;
19   
20 struct edge{ int nt,to; }g[2000010];
21 struct node{ int d,x; }q[1000010];
22   
23 int head[1000010],fa[1000010],f[1000010],cnt[1000010],ans[1000010],n,Q,num;
24 char s[5];
25   
26 il int gi(){
27     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
28     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
29 }
30   
31 il void insert(RG int from,RG int to){ g[++num]=(edge){head[from],to},head[from]=num; return; }
32   
33 il int find(RG int x){ return f[x]==x ? f[x] : f[x]=find(f[x]); }
34   
35 il void unionn(RG int u,RG int v){ f[find(u)]=find(v); return; }
36   
37 il void dfs(RG int x,RG int p){
38     fa[x]=p; RG int v;
39     for (RG int i=head[x];i;i=g[i].nt){
40     v=g[i].to; if (v==p) continue;
41     dfs(v,x); if (!cnt[v]) unionn(v,x);
42     }
43     return;
44 }
45   
46 il void work(){
47     n=gi(),Q=gi(); RG int u,v,x; cnt[1]=1; f[n]=n;
48     for (RG int i=1;i<n;++i) f[i]=i,u=gi(),v=gi(),insert(u,v),insert(v,u);
49     for (RG int i=1;i<=Q;++i){
50     scanf("%s",s); x=gi();
51     if (s[0]=='C') q[i].d=1,q[i].x=x,cnt[x]++;
52     if (s[0]=='Q') q[i].d=2,q[i].x=x;
53     }
54     dfs(1,0); RG int tot=0;
55     for (RG int i=Q;i;--i){
56     if (q[i].d==1){ cnt[q[i].x]--; if (!cnt[q[i].x]) unionn(q[i].x,fa[q[i].x]); }
57     if (q[i].d==2) ans[++tot]=find(q[i].x);
58     }
59     for (RG int i=tot;i;--i) printf("%d\n",ans[i]); return;
60 }
61   
62 int main(){
63     work();
64     return 0;
65 }

 

posted @ 2017-02-22 14:05  wfj_2048  阅读(156)  评论(0编辑  收藏  举报