BZOJ3720: Gty的妹子树
用“重量平衡树”实现的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); } } }