• 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;
    }
    

      

  • 相关阅读:
    栈和堆的详细介绍
    在DataTable中执行DataTable.Select("条件")返回DataTable;
    委托和事件
    面试宝典
    sql的寫法,推薦的寫法,全文索引提高類似like查詢的效率
    Google地图
    一般处理程序中,获取session
    提交表单
    手脱tElock 0.98b1 -> tE!
    手脱FSG 2.0 -> bart/xt
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403219.html
Copyright © 2020-2023  润新知