题目大意
一颗树,除根节点外初始都是白点,根节点是黑点。
每次染黑一个结点或者询问一个结点的最近黑色祖先。
倒序处理
倒着做,于是每次是染白一个结点。
那么就并查集搞呀!
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=100000+10;
struct dong{
int x,ans;
bool p;
} ask[maxn];
int fa[maxn],father[maxn],bz[maxn];
int h[maxn],go[maxn*2],next[maxn*2];
int i,j,k,l,t,n,m,tot;
char ch;
void add(int x,int y){
go[++tot]=y;
next[tot]=h[x];
h[x]=tot;
}
void dfs(int x,int y){
father[x]=y;
int t=h[x];
while (t){
if (go[t]!=y) dfs(go[t],x);
t=next[t];
}
}
void dg(int x,int y){
if (!bz[x]) fa[x]=father[x];
int t=h[x];
while (t){
if (go[t]!=y) dg(go[t],x);
t=next[t];
}
}
int getfa(int x){
return fa[x]?fa[x]=getfa(fa[x]):x;
}
char get(){
char ch=getchar();
while (ch!=‘Q‘&&ch!=‘C‘) ch=getchar();
return ch;
}
int main(){
scanf("%d%d",&n,&m);
fo(i,1,n-1){
scanf("%d%d",&j,&k);
add(j,k);add(k,j);
}
dfs(1,0);
bz[1]=1;
fo(i,1,m){
ch=get();
scanf("%d",&j);
if (ch==‘Q‘){
ask[i].p=1;
ask[i].x=j;
}
else{
ask[i].x=j;
bz[j]++;
}
}
dg(1,0);
fd(i,m,1)
if (ask[i].p) ask[i].ans=getfa(ask[i].x);
else{
bz[ask[i].x]--;
if (!bz[ask[i].x]) fa[ask[i].x]=father[ask[i].x];
}
fo(i,1,m)
if (ask[i].p) printf("%d\n",ask[i].ans);
}
时间: 2024-10-16 08:26:28