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