思路:
对一个节点打标记,就意味着询问这个节点的子树节点都是这个节点,如果有多个父节点被标记,只需要记录深度最深的那个
dfs序遍历树,记录每个点的深度,维护线段树,区间更新点查询,因为我们只要深度最大,所有不用把区间下放,只需要查找整个线段树路径上深度最大的
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <algorithm>
using namespace std;
#define ll long long
#define max_ 100101
#define mod 1000000007
int n,q;
vector< vector<int> >v;
int in[max_],out[max_],deph[max_];
int ti;
struct node
{
int l,r;
int w;
};
struct node tree[max_*4];
void dfs(int u)
{
ti++;
in[u]=ti;
for(int i=0;i<v[u].size();i++)
{
deph[v[u][i]]=deph[u]+1;
dfs(v[u][i]);
}
out[u]=ti;
}
void built(int i,int l,int r)
{
tree[i].l=l;
tree[i].r=r;
tree[i].w=1;
if(l==r)
return;
int mid=(l+r)>>1;
built(i<<1,l,mid);
built(i<<1|1,mid+1,r);
}
void updata(int i,int l,int r,int v)
{
if(tree[i].l==l&&tree[i].r==r)
{
if(deph[v]>deph[tree[i].w])
{
tree[i].w=v;
}
return;
}
int mid=(tree[i].l+tree[i].r)>>1;
if(r<=mid)
updata(i<<1,l,r,v);
else if(l>mid)
updata(i<<1|1,l,r,v);
else
{
updata(i<<1,l,mid,v);
updata(i<<1|1,mid+1,r,v);
}
}
void query(int i,int x,int &v)
{
if(deph[v]<deph[tree[i].w])
v=tree[i].w;
if(tree[i].l==tree[i].r)
return;
int mid=(tree[i].l+tree[i].r)>>1;
if(x<=mid)
query(i<<1,x,v);
else
query(i<<1|1,x,v);
}
int main(int argc, char const *argv[]) {
while(scanf("%d%d",&n,&q)!=EOF)
{
v.clear();
v.resize(n+1);
built(1,1,n);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
v[x].push_back(y);
}
ti=0;
dfs(1);
char c;int x;
while(q--)
{
scanf(" %c%d",&c,&x);
if(c=='Q')
{
int ans=1;
query(1,in[x],ans);
printf("%d\n",ans);
}
else
{
updata(1,in[x],out[x],x);
}
}
}
return 0;
}