[bzoj4551]树

腊鸡树刨套树状数组。。不过并查集才是正解

树刨之后维护一下tag标记,成了一个sumTag了,然后每次查询的时候查询一条链,二分一下寻找深度最小的那个节点,之后递归搞搞就行了。

(其实可以写LCT的。。)

至于并查集的算法的话百度吧

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <map>
 6 #include <string>
 7 #include <vector>
 8 #include <stack>
 9 #include <cmath>
10 #include <queue>
11 #include <cstdio>
12 #include <set>
13 using namespace std;
14 
15 const int N=200000;
16 char str[5];
17 int n,q,u,v,op;
18 int fa[N],top[N],son[N],sz[N],pos[N],id[N],num;
19 int tot=1,head[N],rest[N],to[N];
20 void add(int u,int v){tot++;to[tot]=v;rest[tot]=head[u];head[u]=tot;}
21 int tag[N];
22 void ch(int i){for(;i<=n;i+=i&-i)tag[i]++;}
23 int qy(int i,int c=0){for(;i;i-=i&-i)c+=tag[i];return c;}
24 
25 void dfs(int x){
26     sz[x]=1;
27     for(int i=head[x];i;i=rest[i]){
28         if(to[i]!=fa[x]){
29             fa[to[i]]=x;
30             dfs(to[i]);
31             sz[x]+=sz[to[i]];
32             if(sz[to[i]]>sz[son[x]])son[x]=to[i];
33         }
34     }
35 }
36 void dfs(int x,int tp){
37     top[x]=tp,pos[x]=++num,id[num]=x;
38     if(son[x])dfs(son[x],tp);
39     for(int i=head[x];i;i=rest[i])
40         if(to[i]!=fa[x]&&to[i]!=son[x])dfs(to[i],to[i]);
41 }
42 
43 int ask(int x){
44     if(qy(pos[x])-qy(pos[top[x]]-1)){
45         int l=pos[top[x]],r=pos[x],ans,mid;
46         while(l<=r)(mid=(l+r)>>1),qy(r)-qy(mid-1)?l=mid+1,ans=id[mid]:r=mid-1;
47         return ans;
48     }
49     return ask(fa[top[x]]);
50 }
51 
52 int main(){
53     scanf("%d%d",&n,&q);
54     for(int i=1;i<n;i++)scanf("%d%d",&u,&v),add(u,v),add(v,u);
55     dfs(1),dfs(1,1),ch(1);
56     for(int i=1;i<=q&&scanf("%s%d",str,&op);i++)str[0]=='Q'?printf("%d\n",ask(op)),void():ch(pos[op]);
57 }
View Code

 

posted @ 2017-01-08 09:12  KingSann  阅读(91)  评论(0编辑  收藏  举报