题目描述
输入
数据规模
思路
代码
#include<iostream>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define lc(k) k<<1
#define rc(k) k<<1|1
using namespace std;
const int N=2e6+2,inf=1e9;
struct node
{
int l,r,mid;
int val;
}tree[N];
char op;
int n,q,rt=1,tot;
int a[N],l[N],r[N],st[N][21],dep[N];
int he[N],ne[N],to[N],cnt;
void add(int u,int v)
{
cnt++;
ne[cnt]=he[u];
he[u]=cnt;
to[cnt]=v;
}
void build(int k,int l,int r)
{
tree[k].l=l,tree[k].r=r;
tree[k].val=inf;
if(l==r) return;
tree[k].mid=(l+r)>>1;
build(lc(k),l,tree[k].mid);
build(rc(k),tree[k].mid+1,r);
}
void pushup(int k){tree[k].val=min(tree[lc(k)].val,tree[rc(k)].val);}
void update(int k,int l,int r,int val)
{
if(tree[k].l==l&&tree[k].r==r)
{
tree[k].val=val;
return;
}
if(r<=tree[k].mid) update(lc(k),l,r,val);
if(tree[k].mid+1<=l) update(rc(k),l,r,val);
pushup(k);
}
int query(int k,int l,int r)
{
if(l>r) return inf;
if(tree[k].l==l&&tree[k].r==r)
return tree[k].val;
if(r<=tree[k].mid) return query(lc(k),l,r);
else if(tree[k].mid+1<=l) return query(rc(k),l,r);
else return min(query(lc(k),l,tree[k].mid),query(rc(k),tree[k].mid+1,r));
}
void dfs(int u)
{
l[u]=++tot;
dep[u]=dep[st[u][0]]+1;
update(1,l[u],l[u],a[u]);
for(int i=he[u];i;i=ne[i])
dfs(to[i]);
r[u]=++tot;
}
int main()
{
scanf("%d%d",&n,&q);
build(1,1,2*n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&st[i][0],&a[i]);
if(st[i][0]) add(st[i][0],i);
}
dfs(1);
//求dfs序,建出dfs序区间上的线段树
for(int j=1;j<=20;j++)
for(int i=1;i<=n;i++)
st[i][j]=st[st[i][j-1]][j-1];
//倍增跳祖先
for(int i=1,x,y;i<=q;i++)
{
cin>>op;
if(op=='V')
{
scanf("%d%d",&x,&y);
update(1,l[x],l[x],y);//单点修改
}
if(op=='E')
scanf("%d",&rt);
if(op=='Q')
{
scanf("%d",&x);
if(l[x]<l[rt]&&r[rt]<r[x])//rt在x的子树内 (不含x)
{
y=rt;
for(int step=20;step>=0;step--)
if(dep[st[y][step]]>dep[x]) y=st[y][step];
//将rt跳到x在以1为根情况下的亲儿子
printf("%d\n",min(query(1,1,l[y]-1),query(1,r[y]+1,2*n)));
//查询dfs序区间上的一个前缀和后缀并(整棵树(以1为根)去掉y的子树)
}
else if(x==rt) printf("%d\n",query(1,1,2*n));
//rt为x,查询整棵树
else printf("%d\n",query(1,l[x],r[x]));
//rt在x的子树外,查询dfs序区间上的一个区间((以1为根)x的子树)
}
}
return 0;
}