zoukankan      html  css  js  c++  java
  • 【模板】二逼平衡树

    线段树套splay:

      这是个永远不想打第二遍的模板

      1 #include<bits/stdc++.h>
      2 #define R register
      3 using namespace std;
      4 const int N=50010,NN=2000010,oo=2147483647;
      5 int n,m,a[N];
      6 int fa[NN],ch[NN][2],v[NN],siz[NN],cnt[NN],tot;
      7 int ls[N<<2],rs[N<<2],root[N<<2];
      8 inline int read(){
      9     int x=0,w=1;char c=0;
     10     while(c<'0'||c>'9'){if(c=='-') w=-1;c=getchar();}
     11     while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();
     12     return x*w;
     13 }
     14 struct Splay{
     15     inline bool getside(int k){return ch[fa[k]][1]==k;}
     16     void updata(int k){
     17         siz[k]=cnt[k];
     18         if(ch[k][0]) siz[k]+=siz[ch[k][0]];
     19         if(ch[k][1]) siz[k]+=siz[ch[k][1]];
     20     }
     21     void rotate(int k){
     22         int old=fa[k],oldf=fa[old],sidek=getside(k),sideold=getside(old);
     23         ch[old][sidek]=ch[k][sidek^1];
     24         if(ch[k][sidek^1]) fa[ch[k][sidek^1]]=old;
     25         fa[old]=k,ch[k][sidek^1]=old,fa[k]=oldf;
     26         if(oldf) ch[oldf][sideold]=k;
     27         updata(old);updata(k);
     28         return;
     29     }
     30     void splay(int& r,int k,int aim){
     31         for(int i=fa[k];i!=aim;i=fa[k])
     32             rotate(getside(k)==getside(i)&&fa[i]!=aim?i:k);
     33         if(!aim) r=k;
     34         return;
     35     }
     36     void insert(int& r,int x){
     37         if(!r){
     38             r=++tot;
     39             fa[tot]=0,ch[tot][0]=ch[tot][1]=0,siz[tot]=cnt[tot]=1,v[tot]=x;
     40             return;
     41         }
     42         R int now=r,pre=0;
     43         int side;
     44         while(now){
     45             pre=now;
     46             if(v[now]==x){
     47                 cnt[now]++;
     48                 splay(r,now,0);
     49                 return;
     50             }else if(v[now]>x) now=ch[now][0];
     51             else now=ch[now][1];
     52         }
     53         side=v[pre]<x;
     54         ch[pre][side]=++tot;
     55         fa[tot]=pre,v[tot]=x,cnt[tot]=1;
     56         splay(r,tot,0);
     57         return; 
     58     }
     59     bool find(int& r,int x){ //将值为x的节点旋转到根 
     60         R int now=r;
     61         while(now){
     62             if(v[now]==x){
     63                 splay(r,now,0);
     64                 return 1;
     65             }else if(v[now]>x) now=ch[now][0];
     66             else if(v[now]<x) now=ch[now][1];
     67         }
     68         return 0;
     69     }
     70     int getrnk(int& r,int x){
     71         int ans=0;
     72         R int now=r;
     73         while(now){
     74             if(v[now]==x){
     75                 if(ch[now][0]) ans+=siz[ch[now][0]];
     76                 splay(r,now,0);
     77                 return ans-1;
     78             }else if(v[now]>x){
     79                 now=ch[now][0];
     80             }else{
     81                 ans+=siz[ch[now][0]]+cnt[now];
     82                 now=ch[now][1];
     83             }
     84         }
     85         return ans-1;
     86     }
     87     int getpre(int& r,int x){
     88         R int now=r;
     89         int ans=-oo,anspos=0;
     90         while(now){
     91             if(v[now]>=x){
     92                 now=ch[now][0];
     93             }else{
     94                 if(v[now]>ans) ans=v[now],anspos=now;
     95                 now=ch[now][1];
     96             }
     97         }
     98         if(anspos) splay(r,anspos,0);
     99         return ans;
    100     }
    101     int getnxt(int& r,int x){
    102         R int now=r;
    103         int ans=oo,anspos=0;
    104         while(now){
    105             if(v[now]<=x){
    106                 now=ch[now][1];
    107             }else{
    108                 if(v[now]<ans) ans=v[now],anspos=now;
    109                 now=ch[now][0];
    110             }
    111         }
    112         if(anspos) splay(r,anspos,0);
    113         return ans; 
    114     }
    115     void getprenode(int& r){
    116         R int now=ch[r][0],pre;
    117         while(now) pre=now,now=ch[now][1];
    118         splay(r,pre,r);
    119         return;
    120     }
    121     void del(int &r,int x){
    122         find(r,x);
    123         if(cnt[r]>1){cnt[r]--;updata(r);return;}
    124         if(!ch[r][0]&&!ch[r][1]){r=0;return;}
    125         if(ch[r][0]&&!ch[r][1]){r=ch[r][0],fa[r]=0;return;}
    126         if(!ch[r][0]&&ch[r][1]){r=ch[r][1],fa[r]=0;return;}
    127         getprenode(r);
    128         fa[ch[r][1]]=ch[r][0],ch[ch[r][0]][1]=ch[r][1];
    129         r=ch[r][0],fa[r]=0;
    130         updata(r);
    131         return;
    132     }
    133 }splaytree;
    134 struct Segtree{
    135     void build(int k,int l,int r){
    136         for(int i=l;i<=r;i++) splaytree.insert(root[k],a[i]);
    137         splaytree.insert(root[k],-oo);splaytree.insert(root[k],oo);
    138         ls[k]=l,rs[k]=r;
    139         if(l==r) return;
    140         int mid=(l+r)>>1;
    141         build(k<<1,l,mid);
    142         build(k<<1|1,mid+1,r);
    143         return;
    144     }
    145     void modify(int k,int pos,int x){
    146         splaytree.del(root[k],a[pos]);splaytree.insert(root[k],x); 
    147         if(ls[k]==rs[k]) return;
    148         int mid=(ls[k]+rs[k])>>1;
    149         if(pos<=mid) modify(k<<1,pos,x);
    150         else modify(k<<1|1,pos,x);
    151         return;
    152     }
    153     int quernk(int k,int ql,int qr,int x){
    154         if(ls[k]==ql&&rs[k]==qr)
    155             return splaytree.getrnk(root[k],x);
    156         int mid=(ls[k]+rs[k])>>1;
    157         if(qr<=mid) return quernk(k<<1,ql,qr,x);
    158         else if(ql>mid) return quernk(k<<1|1,ql,qr,x);
    159         else return quernk(k<<1,ql,mid,x)+quernk(k<<1|1,mid+1,qr,x);
    160     }
    161     int quekth(int ql,int qr,int x){
    162         int l=0,r=oo,mid,res,ans;
    163         while(l<=r){
    164             mid=(l+r)>>1;
    165             res=quernk(1,ql,qr,mid)+1;
    166             if(res<=x) l=mid+1,ans=mid;
    167             else r=mid-1;
    168         }
    169         return ans;
    170     }
    171     int quepre(int k,int ql,int qr,int x){
    172         if(ls[k]==ql&&rs[k]==qr)
    173             return splaytree.getpre(root[k],x);
    174         int mid=(ls[k]+rs[k])>>1;
    175         if(qr<=mid) return quepre(k<<1,ql,qr,x);
    176         else if(ql>mid) return quepre(k<<1|1,ql,qr,x);
    177         else return max(quepre(k<<1,ql,mid,x),quepre(k<<1|1,mid+1,qr,x));  
    178     }
    179     int quenxt(int k,int ql,int qr,int x){
    180         if(ls[k]==ql&&rs[k]==qr)
    181             return splaytree.getnxt(root[k],x);
    182         int mid=(ls[k]+rs[k])>>1;
    183         if(qr<=mid) return quenxt(k<<1,ql,qr,x);
    184         else if(ql>mid) return quenxt(k<<1|1,ql,qr,x);
    185         else return min(quenxt(k<<1,ql,mid,x),quenxt(k<<1|1,mid+1,qr,x));
    186     }
    187 }segtree;
    188 int main(){
    189     R int opt,t1,t2,t3;
    190     n=read(),m=read();
    191     for(R int i=1;i<=n;i++) a[i]=read();
    192     segtree.build(1,1,n);
    193     for(R int i=1;i<=m;i++){
    194         opt=read(),t1=read(),t2=read();
    195         if(opt==1){
    196             t3=read();
    197             printf("%d
    ",segtree.quernk(1,t1,t2,t3)+1);
    198         }else if(opt==2){
    199             t3=read();
    200             printf("%d
    ",segtree.quekth(t1,t2,t3));
    201         }else if(opt==3){
    202             segtree.modify(1,t1,t2);
    203             a[t1]=t2;
    204         }else if(opt==4){
    205             t3=read();
    206             printf("%d
    ",segtree.quepre(1,t1,t2,t3));
    207         }else{
    208             t3=read();
    209             printf("%d
    ",segtree.quenxt(1,t1,t2,t3));
    210         }
    211     }
    212     return 0;
    213 }
  • 相关阅读:
    Redis 哨兵机制以及灾难演练
    经典的Redis的主从复制搭建
    Redis的几个核心机制底层原理
    Redis Sentinel(哨兵核心机制) 初步深入
    从零开始装CentOS以及配置Redis,前端都可以!!!
    在项目中部署redis的读写分离架构(包含节点间认证口令)
    读懂MySQL执行计划
    SpringBoot之自动配置原理
    排序算法总结
    拉格朗日插值法理论与编程实现
  • 原文地址:https://www.cnblogs.com/mycups/p/8549044.html
Copyright © 2011-2022 走看看