可以用并查集,记忆化搜索,线段树多种方法实现。
我这里写的是依照dfs序建线段树,维护区间最大值。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=100005; 4 int head[N],lz[N<<2],t[N<<2],id[N],end[N],cnt,idx,pos[N]; 5 struct node 6 { 7 int to,nex; 8 }e[N<<1]; 9 void add(int x,int y) 10 { 11 e[++cnt].to=y;e[cnt].nex=head[x];head[x]=cnt; 12 } 13 void dfs(int x,int fa) 14 { 15 id[x]=++idx;pos[idx]=x; 16 for(int i=head[x];i;i=e[i].nex) 17 { 18 int y=e[i].to; 19 if(y==fa)continue; 20 dfs(y,x); 21 } 22 end[x]=idx; 23 } 24 void pushdown(int x) 25 { 26 if(lz[x]) 27 { 28 t[x<<1]=max(t[x<<1],lz[x]); 29 t[x<<1|1]=max(t[x<<1|1],lz[x]); 30 lz[x<<1]=max(lz[x],lz[x<<1]); 31 lz[x<<1|1]=max(lz[x],lz[x<<1|1]); 32 lz[x]=0; 33 } 34 } 35 void update(int p,int l,int r,int L,int R,int w) 36 { 37 if(l==L&&r==R) 38 { 39 t[p]=max(t[p],w);lz[p]=max(lz[p],w);return; 40 } 41 int mid=l+r>>1;pushdown(p); 42 if(R<=mid)update(p<<1,l,mid,L,R,w); 43 else if(L>mid)update(p<<1|1,mid+1,r,L,R,w); 44 else update(p<<1,l,mid,L,mid,w),update(p<<1|1,mid+1,r,mid+1,R,w); 45 } 46 int query(int p,int l,int r,int pos) 47 { 48 if(l==r)return t[p]; 49 int mid=l+r>>1;pushdown(p); 50 if(pos<=mid)return query(p<<1,l,mid,pos); 51 else if(pos>mid)return query(p<<1|1,mid+1,r,pos); 52 } 53 int main() 54 { 55 //freopen("tree.in","r",stdin); 56 //freopen("tree.out","w",stdout); 57 int n,q;scanf("%d%d",&n,&q); 58 for(int i=1;i<n;++i) 59 { 60 int x,y; 61 scanf("%d%d",&x,&y); 62 add(x,y); 63 add(y,x); 64 } 65 dfs(1,0); 66 update(1,1,n,id[1],end[1],1); 67 for(int i=1;i<=q;++i) 68 { 69 char s[3];int x;scanf("%s",s);scanf("%d",&x); 70 if(s[0]=='C') 71 { 72 update(1,1,n,id[x],end[x],id[x]); 73 } 74 else 75 { 76 printf("%d ",pos[query(1,1,n,id[x])]); 77 } 78 } 79 return 0; 80 }