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 }
  • 相关阅读:
    cmanformat
    mysql-sql语言参考
    jQuery 判断多个 input checkbox 中至少有一个勾选
    Java实现 蓝桥杯 算法提高 计算行列式
    Java实现 蓝桥杯 数独游戏
    Java实现 蓝桥杯 数独游戏
    Java实现 蓝桥杯 数独游戏
    Java实现 蓝桥杯 算法提高 成绩排序2
    Java实现 蓝桥杯 算法提高 成绩排序2
    Java实现 蓝桥杯 算法提高 成绩排序2
  • 原文地址:https://www.cnblogs.com/mycups/p/8549044.html
Copyright © 2011-2022 走看看