BZOJ3720 : Gty的妹子树
如果没有插入操作,那么直接对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; }