如果没有插入操作,那么直接对DFS序建立线段树套平衡树即可,
有插入操作的话,将外层的线段树换成重量平衡树即可。
一开始写替罪羊树套权值线段树无限MLE…
所以只好写替罪羊树套Treap…
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef unsigned int uint;
const int N=120010;
struct node{
int val,cnt,sum,p;node *l,*r;
node(){val=cnt=sum=p=0;l=r=NULL;}
inline void up(){sum=cnt+l->sum+r->sum;}
}*blank=new(node);
const double A=0.7;
int size[N],son[N][2],val[N],f[N],tot,root,deep;
int data[N],id[N],cnt;
node *h[N];
int g[N],nxt[N],to[N],ed,w[N];
int st[N],en[N],dfn,ans;
//Init begin
inline void add(int x,int y){to[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
void dfstree(int x,int pre){
data[st[x]=++dfn]=w[x];
for(int i=g[x];i;i=nxt[i])if(to[i]!=pre)dfstree(to[i],x);
en[x]=++dfn;
}
//Init end
//Treap begin
inline void Rotatel(node*&x){node*y=x->r;x->r=y->l;x->up();y->l=x;y->up();x=y;}
inline void Rotater(node*&x){node*y=x->l;x->l=y->r;x->up();y->r=x;y->up();x=y;}
void Insert(node*&x,int p){
if(x==blank){
x=new(node);x->val=p;x->l=x->r=blank;x->cnt=x->sum=1;x->p=rand();
return;
}
x->sum++;
if(p==x->val){x->cnt++;return;}
if(p<x->val){
Insert(x->l,p);
if(x->l->p>x->p)Rotater(x);
}else{
Insert(x->r,p);
if(x->r->p>x->p)Rotatel(x);
}
}
void Delete(node*&x,int p){
x->sum--;
if(p==x->val){x->cnt--;return;}
if(p<x->val)Delete(x->l,p);else Delete(x->r,p);
}
int Ask(node*&x,int p){
if(x==blank)return 0;
if(p==x->val)return x->r->sum;
if(p<x->val)return x->cnt+x->r->sum+Ask(x->l,p);
return Ask(x->r,p);
}
void deltree(node*&x){
if(x==blank)return;
if(x->l)deltree(x->l);if(x->r)deltree(x->r);
delete(x);
}
//Treap end
//Scapegoat begin
inline int newnode(int x,int p,int fa){
f[x]=fa;size[x]=1;son[x][0]=son[x][1]=0;
val[x]=p;
Insert(h[x]=blank,p);
return x;
}
inline int Newnode(int x,int p,int fa){
f[x]=fa;size[x]=1;son[x][0]=son[x][1]=0;
val[x]=p;
h[x]=blank;
return x;
}
int ins(int x,int p,int b){
size[x]++;
Insert(h[x],p);
if(!son[x][b])return son[x][b]=newnode(++tot,p,x);else return ins(son[x][b],p,b);
}
void dfs(int x){
if(son[x][0])dfs(son[x][0]);
data[++cnt]=val[x];id[cnt]=x;
if(son[x][1])dfs(son[x][1]);
}
int build(int fa,int l,int r){
int mid=(l+r)>>1,x=Newnode(id[mid],data[mid],fa);
for(int i=l;i<=r;i++)Insert(h[x],data[i]);
if(l==r)return x;
if(l<mid)size[x]+=size[son[x][0]=build(x,l,mid-1)];
if(r>mid)size[x]+=size[son[x][1]=build(x,mid+1,r)];
return x;
}
inline int rebuild(int x){
cnt=0;dfs(x);
for(int i=1;i<=cnt;i++)deltree(h[id[i]]);
return build(f[x],1,cnt);
}
inline int kth(int k,int p){
int x=root,rank,t;
while(1){
size[x]++;Insert(h[x],p);
rank=size[son[x][0]]+1;
if(k==rank)return x;
if(k<rank)x=son[x][0];else k-=rank,x=son[x][1];
}
}
inline void kthchange(int K,int p){
int x=root,rank,t,k=K,del;
while(1){
rank=size[son[x][0]]+1;
if(k==rank){del=val[x];break;}
if(k<rank)x=son[x][0];else k-=rank,x=son[x][1];
}
x=root,k=K;
while(1){
Delete(h[x],del);
Insert(h[x],p);
rank=size[son[x][0]]+1;
if(k==rank){val[x]=p;return;}
if(k<rank)x=son[x][0];else k-=rank,x=son[x][1];
}
}
inline int rank(int x){
int ans=size[son[x][0]]+1;
while(f[x]){
if(son[f[x]][1]==x)ans+=size[son[f[x]][0]]+1;
x=f[x];
}
return ans;
}
inline void kthins(int k,int p){
if(!root){root=newnode(++tot,p,0);return;}
int x;
if(k==1)x=ins(root,p,0);
else if(k>tot)x=ins(root,p,1);
else{
x=kth(k,p);
if(son[x][0])x=ins(son[x][0],p,1);else{
son[x][0]=newnode(++tot,p,x);
x=son[x][0];
}
}
deep=0;int z=x;while(f[z])z=f[z],deep++;
if(deep<log(tot)/log(1/A))return;
while((double)size[son[x][0]]<A*size[x]&&(double)size[son[x][1]]<A*size[x])x=f[x];
if(!x)return;
if(x==root){root=rebuild(x);return;}
int y=f[x],b=son[y][1]==x,now=rebuild(x);
son[y][b]=now;
}
inline void ask(int x,int a,int b,int c,int d,int k){
if(!x)return;
if(c<=a&&b<=d){ans+=Ask(h[x],k);return;}
int mid=a+size[son[x][0]];
if(c<=mid&&mid<=d)ans+=val[x]>k;
if(c<mid)ask(son[x][0],a,mid-1,c,d,k);
if(d>mid)ask(son[x][1],mid+1,b,c,d,k);
}
//Scapegoat end
inline void read(int&a){
char ch;while(!(((ch=getchar())>='0')&&(ch<='9')));
a=ch-'0';while(((ch=getchar())>='0')&&(ch<='9'))(a*=10)+=ch-'0';
}
int n,q,x,y,k,i,ch;
int main(){
blank->l=blank->r=blank;
read(n);
for(i=1;i<n;i++)read(x),read(y),add(x,y),add(y,x);
for(i=1;i<=n;i++)read(w[i]);
dfstree(1,0);
for(i=1;i<=dfn;i++)id[i]=i;
root=build(0,1,tot=dfn);
read(q);
while(q--){
read(ch),read(x),read(y),x^=ans,y^=ans;
if(!ch){
ans=0;
ask(root,1,tot,rank(st[x]),rank(en[x]),y);
printf("%d\n",ans);
}else if(ch==1){
kthchange(rank(st[x]),y);
}else{
st[++n]=tot+2,en[n]=tot+1;
kthins(k=rank(en[x]),0);
kthins(k,y);
}
}
return 0;
}