并不是太难,只要处理换根操作就好了,因为这棵树的形态是不变的。那么按照点1为根时的dfs序,若当前根在x点的子树外,则答案还是x的子树,若当前根是x,那么答案是整棵树,若当前的根在x的子树内,则答案就是抠掉根所在的那一枝后的答案(画个图就明白了)。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 100010
#define inf 1000000000
using namespace std;
struct yts
{
int data;
int l,r;
}a[4*maxn];
int e[maxn],next[2*maxn],head[maxn],to[2*maxn],g[maxn],w[maxn],in[maxn],out[maxn];
int fa[maxn][20],dep[maxn];
int n,m,root,num,T,tot;
void addedge(int x,int y)
{
num++;to[num]=y;next[num]=head[x];head[x]=num;
}
void dfs(int x)
{
e[++tot]=x;in[x]=tot;
for (int p=head[x];p;p=next[p])
if (to[p]!=g[x]) dep[to[p]]=dep[x]+1,dfs(to[p]);
out[x]=tot;
}
void build(int i,int l,int r)
{
a[i].l=l;a[i].r=r;
if (l==r) {a[i].data=w[e[l]];return;}
int mid=(l+r)/2;
build(i*2,l,mid);build(i*2+1,mid+1,r);
a[i].data=min(a[i*2].data,a[i*2+1].data);
}
void modify(int i,int x,int d)
{
if (a[i].l==a[i].r) {a[i].data=d;return;}
int mid=(a[i].l+a[i].r)/2;
if (x<=mid) modify(i*2,x,d);
if (mid<x) modify(i*2+1,x,d);
a[i].data=min(a[i*2].data,a[i*2+1].data);
}
int query(int i,int l,int r)
{
if (l>r) return inf;
if (l<=a[i].l && a[i].r<=r) return a[i].data;
int mid=(a[i].l+a[i].r)/2,ans=inf;
if (l<=mid) ans=min(ans,query(i*2,l,r));
if (mid<r) ans=min(ans,query(i*2+1,l,r));
return ans;
}
int go_up(int x,int d)
{
for (int i=19;i>=0;i--)
if (d&(1<<i)) x=fa[x][i];
return x;
}
int main()
{
scanf("%d%d",&n,&T);
for (int i=1;i<=4*n;i++) a[i].data=inf;
for (int i=1;i<=n;i++)
scanf("%d%d",&g[i],&w[i]);
for (int i=1;i<=n;i++)
if (g[i]) addedge(g[i],i);
else root=i;
dep[1]=0;dfs(1);
for (int i=1;i<=n;i++) fa[i][0]=g[i];
for (int j=1;j<=19;j++)
for (int i=1;i<=n;i++)
if (fa[i][j-1]) fa[i][j]=fa[fa[i][j-1]][j-1];
else fa[i][j]=0;
build(1,1,n);
while (T--)
{
char op[5];
int x,y;
scanf("%s%d",op,&x);
if (op[0]=='V')
{
scanf("%d",&y);
modify(1,in[x],y);
}
if (op[0]=='E') root=x;
if (op[0]=='Q')
{
if (root==x) printf("%d\n",query(1,1,n));
else
if (in[x]<=in[root] && out[root]<=out[x])
{
int y=go_up(root,dep[root]-dep[x]-1);
printf("%d\n",min(query(1,1,in[y]-1),query(1,out[y]+1,n)));
}
else printf("%d\n",query(1,in[x],out[x]));
}
}
return 0;
}