用“重量平衡树”实现的ETT套平衡树就可以做到$O(n\log^2n)$了。然而我很无聊地写了个$O(n\sqrt{n\log n})$的根号重构,就是每$O(\sqrt{n\log n})$次修改就用$O(n\log n)$的代价重构函数式trie。
#include<cstdio>
#include<vector>
#define pb push_back
const int N=60005;
struct node{
node*i,*j;
int s;
}e[N*30];
node*now,*r[N];
void ins(int k,node**o){
for(int i=29;~i;--i){
*++now=**o,*o=now;
if(~k>>i&1)o=&(*o)->i;
else
++(*o)->s,o=&(*o)->j;
}
}
int ask(int k,node*o){
int s=0;
for(int i=29;~i;--i)
if(k>>i&1)o=o->j;
else
s+=o->s,o=o->i;
return s;
}
int ask(int k,int u,int v){
return ask(k,r[v])-ask(k,r[u-1]);
}
int dfn,p[N],f1[N],f2[N],w[N],f3[N],vis[N];
std::vector<int>c,t,g[N];
void dfs(int u){
f1[u]=++dfn,r[dfn]=r[dfn-1],ins(w[u],r+dfn);
for(int i=0;i<g[u].size();++i){
int v=g[u][i];
if(v!=p[u])p[v]=u,dfs(v);
}
f2[u]=dfn;
}
int dfs2(int u,int k){
int s=w[u]>k;
for(int i=0;i<g[u].size();++i){
int v=g[u][i];
if(v!=p[u])s+=dfs2(v,k);
}
return s;
}
bool jud(int v,int u){
return f1[u]<=f1[v]&&f1[v]<=f2[u];
}
void reb(){
for(int i=0;i<c.size();++i)
w[c[i]]=t[i];
c.clear();
t.clear();
dfn=0,now=e,dfs(1);
}
int main(){
*(*r=e)={e,e};
int n,m,o,u,v,s=0;
scanf("%d",&n);
for(int i=2;i<=n;++i)
scanf("%d%d",&u,&v),g[u].pb(v),g[v].pb(u);
for(int i=1;i<=n;++i)
scanf("%d",w+i);
reb();
scanf("%d",&m);
for(int k=1;k<=m;++k){
scanf("%d%d%d",&o,&u,&v),u^=s,v^=s;
if(!o){
if(c.size()+n-dfn>3000)
reb();
if(u>dfn)s=dfs2(u,v);
else{
s=ask(v,f1[u],f2[u]);
for(int i=c.size()-1;~i;--i)
if(jud(c[i],u)&&k!=vis[c[i]]){
vis[c[i]]=k;
if(w[c[i]]>v)--s;
if(t[i]>v)++s;
}
for(int i=n;i>dfn;--i)
if(jud(f3[i],u))s+=w[i]>v;
}
printf("%d\n",s);
}
if(o==1)
if(u>dfn)w[u]=v;
else
c.pb(u),t.pb(v);
if(o==2){
++n,p[n]=u,w[n]=v;
f3[n]=u>dfn?f3[u]:u;
g[u].pb(n);
g[n].pb(u);
}
}
}