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
",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;
}

  

原文地址:https://www.cnblogs.com/clrs97/p/4403219.html