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;

}

  

 

你可能感兴趣的:(ZOJ)