[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 }

浙公网安备 33010602011771号