[HEOI2016/TJOI2016]树
就上树剖。
维护区间最右端的点。
主要是顺手复习一下树剖。
30min手速很不错。
#include<iostream>
#include<cstdio>
#define ll long long
#define N 100005
ll n;
ll head[N];
struct P{
int to,next;
}e[N << 1];
ll cnt;
inline void add(int x,int y){
e[++cnt].to = y;
e[cnt].next = head[x];
head[x] = cnt;
}
ll q;
ll siz[N],dfn[N],idfn[N],dep[N],son[N],top[N],fa[N];
inline void dfs1(int x,int f){
siz[x] = 1;
dep[x] = dep[f] + 1;
fa[x] = f;
for(int i = head[x];i;i = e[i].next){
int v = e[i].to;
if(v == f)continue;
dfs1(v,x);
if(siz[v] > siz[son[x]])
son[x] = v;
siz[x] += siz[v];
}
}
ll dfncnt;
inline void dfs2(int u,int t){
dfn[u] = ++dfncnt;
idfn[dfncnt] = u;
top[u] = t;
if(son[u])dfs2(son[u],t);
for(int i = head[u];i;i = e[i].next){
int v = e[i].to;
if(v == fa[u] || v == son[u])continue;
dfs2(v,v);
}
}
struct Tree{int right;}T[N << 4];
#define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)
#define root 1,1,n
#define r(x) T[x].right
#define mid ((l + r) >> 1)
inline void up(int x){
if(r(rs(x)))
r(x) = r(rs(x));
else
r(x) = r(ls(x));
}
inline void Add(int x,int l,int r,int to){
if(l == r){
r(x) = idfn[l];
return;
}
if(to <= mid)
Add(ls(x),l,mid,to);
else
Add(rs(x),mid + 1,r,to);
up(x);
}
inline ll find(int x,int l,int r,int tl,int tr){
if(tl <= l && r <= tr){
return r(x);
}
ll p = 0;
if(tr > mid)
p = find(rs(x),mid + 1,r,tl,tr);
if(!p && tl <= mid)
p = find(ls(x),l,mid,tl,tr);
return p;
}
int main(){
scanf("%lld%lld",&n,&q);
for(int i = 1;i < n;++i){
ll x,y;
scanf("%lld%lld",&x,&y);
add(x,y);
add(y,x);
}
dfs1(1,0);
dfs2(1,1);
Add(root,1);
while(q -- ){
char a = getchar();
while(a != 'C' && a != 'Q')
a = getchar();
if(a == 'C'){
ll x;
scanf("%lld",&x);
Add(root,dfn[x]);
}
if(a == 'Q'){
ll ans = 0;
ll x;
scanf("%lld",&x);
while(x){
ans = find(root,dfn[top[x]],dfn[x]);
if(ans)
break;
x = fa[top[x]];
}
std::cout<<ans<<std::endl;
}
a = '.';
}
}