主席树/可持久化线段树/数组

int idx;
//目前一共建立过多少节点 
int sum[N<<2],ls[N<<2],rs[N<<2];

int root[N];
//每次修改对应的根节点编号 


//建立空树
void build(int &k,int l,int r){
    k=++idx;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(ls[k],l,mid);
    build(rs[k],mid+1,r);
} 
//修改操作
void change(int kp,int &k,int l,int r,int p,int d){
    k=++idx;
    ls[k]=ls[kp],rs[k]=rs[kp];
    sum[k]=sum[kp]+d;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(p<=mid) change(ls[k],ls[k],l,mid,p,d);
    else change(rs[k],rs[k],mid+1,r,p,d);
}
//区间和查询
int query(int k,int l,int r,int x,int y){
    if(x<=l&&r<=y) return sum[k];
    int mid=(l+r)>>1,ans=0;
    if(x<=mid) ans+=query(ls[k],l,mid,x,y);
    if(mid<y) ans+=query(rs[k],mid+1,r,x,y);
    return ans;
} 
//可持久化线段树注意事项:

//1.取地址
//2.先建点,后if(l==r)return
//3.空间开(n+Qlogn)

主席树操作模板

例题:1.可持久化线段树1(主席树) luogu模板 3834 静态区间第k大

利用主席树构建前缀树,将数据离散化后按照大小放入前缀树中,最后查找x-1和y两棵树内情况找到第k大的编号,最后根据离散化后的数组输出真实值

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
#define dec(i,x,y) for(register int i=x;i>=y;i--)
#define ll long long
using namespace std;
const int N=200050;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;}
namespace zjc{
     
     int n,m,q,idx,a[N],b[N],root[N];
     int ls[N<<5],rs[N<<5],sum[N<<5];
     
     inline void build(int &k,int l,int r){
          k=++idx;
          if(l==r) return;
          int mid=(l+r)>>1;
          build(ls[k],l,mid);
          build(rs[k],mid+1,r);
     }
     inline void change(int &k,int kp,int l,int r,int p){
          k=++idx;
          ls[k]=ls[kp],rs[k]=rs[kp],sum[k]=sum[kp]+1;
          if(l==r) return;
          int mid=(l+r)>>1;
          if(p<=mid) change(ls[k],ls[kp],l,mid,p);
          else change(rs[k],rs[kp],mid+1,r,p);
     }
     inline int query(int x,int y,int l,int r,int k){
          if(l==r) return l;
          int mid=(l+r)>>1,s=sum[ls[y]]-sum[ls[x]];
          if(k<=s) return query(ls[x],ls[y],l,mid,k);
         else return query(rs[x],rs[y],mid+1,r,k-s); 
     }
     inline int find(int x){
          return lower_bound(b+1,b+1+m,x)-b;} 

      void work(){
          n=read(),q=read();
          rep(i,1,n) a[i]=read(),b[i]=a[i];
          sort(b+1,b+1+n);
          m=unique(b+1,b+1+n)-(b+1);
          build(root[0],1,m);
         
          rep(i,1,n) change(root[i],root[i-1],1,m,find(a[i]));
         
          while(q--){
               int x,y,z;
               x=read(),y=read(),z=read();
               int t=query(root[x-1],root[y],1,m,z);
               printf("%d\n",b[t]);
          }
          return;
     }
}

int main(){
    zjc::work();
    return 0;
}

2.可持久化数组 luogu 模板3919 回到历史版本

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
#define ll long long
using namespace std;
const int N=1000050;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;}
namespace zjc{
    int n,m,idx,a[N],root[N<<5];
    int ls[N<<5],rs[N<<5],mx[N<<5];
    int v,k,p,val,s;

    inline void build(int &k,int l,int r){
        k=++idx;
        if(l==r){mx[k]=a[l];return;}
        int mid=(l+r)>>1;
        build(ls[k],l,mid);build(rs[k],mid+1,r);
    }
    inline void change(int &k,int kp,int l,int r,int p,int d){
        k=++idx;ls[k]=ls[kp],rs[k]=rs[kp],mx[k]=mx[kp];
        if(l==r) {mx[k]=d;return;}
        int mid=(l+r)>>1; 
        if(p<=mid) change(ls[k],ls[kp],l,mid,p,d);
        else change(rs[k],rs[kp],mid+1,r,p,d);
    }
    inline int query(int k,int l,int r,int p){
        if(l==r) return mx[k];
        int mid=(l+r)>>1;
        if(p<=mid) return query(ls[k],l,mid,p);
        else return query(rs[k],mid+1,r,p);
    }
    void work(){
        n=read(),m=read();
        rep(i,1,n) a[i]=read();
        build(root[0],1,n);
        rep(i,1,m){
            int pre=read(),opt=read(),p=read();
            if(opt==1){int v=read();change(root[i],root[pre],1,n,p,v);}
            if(opt==2){printf("%d\n",query(root[pre],1,n,p));root[i]=root[pre];}}
        return;    
    }
}
int main(){
    zjc::work();
    return 0;
}

3.可持久化平衡树

以后填坑吧,splay treap都不咋会

 

posted @ 2018-09-12 10:48  ASDIC减除  阅读(105)  评论(0编辑  收藏  举报