第一反应是dfs序+线段树,一个节点打上标记,就对整棵子树,下推标记时判断一下深度
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=100005;
struct egde {
int t,next;
}e[N<<1];
struct tree {
int ans;
}tr[N<<2];
int cnt,n,m,num;
int head[N],wei[N],law[N],dee[N];
void ans(int u,int t){
e[++cnt].t=t;
e[cnt].next=head[u];
head[u]=cnt;
}
void build(int ts,int l,int r){
tr[ts].ans=0;tr[ts].ans=1;
if (l==r) return;
int mid=(l+r)>>1;
build(ts<<1,l,mid);
build(ts<<1|1,mid+1,r);
}
void dfs(int u,int fa){
wei[u]=++num;dee[u]=dee[fa]+1;;
for (int i=head[u];i;i=e[i].next){
int v=e[i].t;
if (v==fa) continue;
dfs(v,u);
}
law[u]=num;
}
int get(int x,int y){return dee[x]>dee[y]?x:y;}
void pushdown(int ts){
if (!tr[ts].ans) return;
int k=tr[ts].ans;tr[ts].ans=0;
tr[ts<<1].ans=get(k,tr[ts<<1].ans);
tr[ts<<1|1].ans=get(k,tr[ts<<1|1].ans);
}
void update(int ts,int l,int r,int L,int R,int k){
if (l==L && r==R) {
tr[ts].ans=get(k,tr[ts].ans);
return;
}
int mid=(l+r)>>1;
pushdown(ts);
if (L>mid) update(ts<<1|1,mid+1,r,L,R,k);
else if (R<=mid) update(ts<<1,l,mid,L,R,k);
else {
update(ts<<1,l,mid,L,mid,k);update(ts<<1|1,mid+1,r,mid+1,R,k);
}
}
int query(int ts,int l,int r,int k){
if (l==r) return tr[ts].ans;
int mid=(l+r)>>1;
pushdown(ts);
if (k<=mid) return query(ts<<1,l,mid,k);
else return query(ts<<1|1,mid+1,r,k);
}
#define dd a=getchar()
void read(char &a,int &b){
while(dd,a!='Q' && a!='C');
scanf("%d",&b);
}
#undef dd
int main(){
// freopen("hh.in","r",stdin);
scanf("%d%d",&n,&m);
for (int i=1;i<n;i++){
int a,b;
scanf("%d%d",&a,&b);
ans(a,b);ans(b,a);
}
dfs(1,0);
update(1,1,n,1,n,1);
for (int i=1;i<=m;i++){
char a;int b;
read(a,b);
if (a=='Q') {
printf("%d\n",query(1,1,n,wei[b]));
}
else {
update(1,1,n,wei[b],law[b],b);
}
}
}
F2:并查集,逆序操作,有标记的节点的父亲是自己,不然是父亲节点。每次查询找祖先,消节点改变父亲
#include <cstdio>
using namespace std;
const int N=100005;
struct egde {
int t,next;
}e[N<<1];
struct quer{
int id,x;
}qu[N];
int cnt,n,m;
int head[N],mar[N],fa[N],f[N],ans[N];
void add(int u,int t){
e[++cnt].t=t;
e[cnt].next=head[u];
head[u]=cnt;
}
void dfs(int u,int fa){
f[u]=fa;
for (int i=head[u];i;i=e[i].next){
int v=e[i].t;
if (v==fa) continue;
dfs(v,u);
}
}
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
#define dd a=getchar()
void read(char &a,int &b){
while(dd,a!='Q' && a!='C');
scanf("%d",&b);
}
#undef dd
int main(){
// freopen("hh.in","r",stdin);
scanf("%d%d",&n,&m);
for (int i=1;i<n;i++){
int a,b;
scanf("%d%d",&a,&b);
add(a,b);add(b,a);
}
dfs(1,1);mar[1]=1;
for (int i=1;i<=m;i++){
char a;int b;
read(a,b);
if (a=='Q') {
qu[i].id=0;qu[i].x=b;
}
else {
mar[b]++;
qu[i].id=1;qu[i].x=b;
}
}
for (int i=1;i<=n;i++)
if (!mar[i]) fa[i]=f[i];
else fa[i]=i;
for (int i=m;i>=1;i--){
if (!qu[i].id) {
ans[i]=find(qu[i].x);
}
else {
mar[qu[i].x]--;
if (!mar[qu[i].x]) fa[qu[i].x]=f[qu[i].x];
}
}
for (int i=1;i<=m;i++)
if (!qu[i].id) printf("%d\n",ans[i]);
}