单点修改 , 链查询查到了就break
线段树查询时先找到区间 , 区间内尽量往右边找 , 这样深度更大
#include<bits/stdc++.h>
#define N 100050
#define M N*2
using namespace std;
int n,m,tag[N];
int first[N],next[M],to[M],tot;
int id[N],siz[N],dep[N],fa[N],son[N],top[N],pre[N],sign;
int val[N<<2];
void add(int x,int y){
next[++tot]=first[x],first[x]=tot,to[tot]=y;
}
void dfs1(int u,int f){
siz[u]=1;
for(int i=first[u];i;i=next[i]){
int t=to[i]; if(t==f) continue;
fa[t] = u , dep[t] = dep[u] + 1;
dfs1(t,u); siz[u] += siz[t];
if(siz[son[u]]<siz[t]) son[u] = t;
}
}
void dfs2(int u,int Top){
id[u] = ++sign; pre[sign] = u;
top[u] = Top;
if(son[u]) dfs2(son[u],Top);
for(int i=first[u];i;i=next[i]){
int t=to[i]; if(t==son[u] || t==fa[u]) continue;
dfs2(t,t);
}
}
void Pushup(int x){
val[x] = val[x<<1] + val[x<<1|1];
}
void Insert(int x,int l,int r,int pos,int v){
if(l==r){ val[x] = v; return;}
int mid = (l+r) >> 1;
if(pos<=mid) Insert(x<<1,l,mid,pos,v);
else Insert(x<<1|1,mid+1,r,pos,v);
Pushup(x);
}
void Q(int x,int l,int r,int &ans){
if(l==r && val[x]){ ans = max(ans,l); return;}
int mid = (l+r) >> 1;
if(val[x<<1|1]) Q(x<<1|1,mid+1,r,ans);
else Q(x<<1,l,mid,ans);
}
void Tree_Q(int x,int l,int r,int L,int R,int &ans){
if(L<=l && r<=R){
if(val[x]) Q(x,l,r,ans); return;
}
int mid = (l+r) >> 1;
if(L<=mid) Tree_Q(x<<1,l,mid,L,R,ans);
if(R>mid) Tree_Q(x<<1|1,mid+1,r,L,R,ans);
}
int Quary(int x){
while(top[x]!=1){
int tmp=0; Tree_Q(1,1,n,id[top[x]],id[x],tmp);
if(tmp) return pre[tmp];
x = fa[top[x]];
} int tmp = 0; Tree_Q(1,1,n,id[1],id[x],tmp);
return pre[tmp];
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++){
int x,y; scanf("%d%d",&x,&y);
add(x,y),add(y,x);
} dfs1(1,0); dfs2(1,1);
tag[1] = 1; Insert(1,1,n,1,id[1]);
while(m--){
char s[3]; scanf("%s",s); int x; scanf("%d",&x);
if(s[0]=='Q') printf("%d\n",Quary(x));
if(s[0]=='C') if(!tag[x]) Insert(1,1,n,id[x],1), tag[x] = 1;
} return 0;
}