首页 > 代码库 > 【TJOI&HEOI2016】【Bzoj4551】树

【TJOI&HEOI2016】【Bzoj4551】树

这道题是可以用树链剖分来做的,但其实有比它更加简单的做法——并查集。

可以想到,这类题的一种常见做法是离线处理,先全部读入,再从后往前处理,每次遇到标记操作,就把这个点的标记次数减一,到零以后就把这个点的前继连到它的父亲上。

然后再倒序输出答案即可。

Code:

技术分享
 1 #include<cstdio>
 2 #include<vector>
 3 using namespace std;
 4 const int maxn=100010;
 5 struct data{
 6     char str[2];
 7     int dot;
 8 }query[maxn];
 9 int ans[maxn];
10 int n,q,mark[maxn],fa[maxn],par[maxn],t=0;
11 vector <int> a[maxn];
12 void readin(){
13     scanf("%d%d",&n,&q);
14     mark[1]=1;
15     for (int i=1; i<n; i++){
16         int u,v;
17         scanf("%d%d",&u,&v);
18         a[u].push_back(v);
19         a[v].push_back(u);
20     }
21     for (int i=1; i<=q; i++){
22         scanf("%s%d",query[i].str,&query[i].dot);
23         if (query[i].str[0]==C) mark[query[i].dot]++;
24     }
25 }
26 int find(int x){
27     if (par[x]==x) return x;
28     else return par[x]=find(par[x]);
29 }
30 void dfs(int s,int p){
31     if (mark[s]) par[s]=s;
32     else par[s]=find(p);
33     for (int i=0; i<a[s].size(); i++){
34         int now=a[s][i];
35         if (now==p) continue;
36         fa[now]=s;
37         dfs(now,s);
38     }
39 }
40 void solve(){
41     dfs(1,0);
42     for (int i=q; i>0; i--){
43         if (query[i].str[0]==Q){
44             ans[++t]=find(query[i].dot);
45         }
46         else {
47             int now=query[i].dot;
48             mark[now]--;
49             if (mark[now]==0) par[now]=find(fa[now]);
50         } 
51     }
52 }
53 void putout(){
54     for (int i=t; i>=1; i--) printf("%d\n",ans[i]);  
55 }
56 int main(){
57     readin();
58     solve();
59     putout();
60     return 0;
61 }
View Code

 

【TJOI&HEOI2016】【Bzoj4551】树