zoukankan      html  css  js  c++  java
  • Splay 模板

     

      今天2.12,我发现下面的代码有bug(bug在delete()里,有些情况没有考虑到),对于bzoj3224可以过,但是改造一下过不了NOI2004郁闷的出纳员,目前又改了两天把我写的最靠谱的代码放在最下面。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cmath>
      5 #include<algorithm>
      6 #include<queue>
      7 #include<vector>
      8 using namespace std;
      9 const int maxn=200000;
     10 int key[maxn],lc[maxn],rc[maxn],fa[maxn],siz[maxn];
     11 int tot,root;
     12 int T;
     13 void update(int x){
     14     siz[x]=siz[lc[x]]+1+siz[rc[x]];
     15 }
     16 void r_rotate(int x){
     17     int y=fa[x];
     18     lc[y]=rc[x]; fa[rc[x]]=y; fa[x]=fa[y];
     19     if(y==lc[fa[y]]) lc[fa[y]]=x;
     20     else rc[fa[y]]=x;
     21     fa[y]=x; rc[x]=y;
     22     update(x); update(y);
     23 }
     24 void l_rotate(int x){
     25     int y=fa[x];
     26     rc[y]=lc[x]; fa[lc[x]]=y; fa[x]=fa[y];
     27     if(y==lc[fa[y]]) lc[fa[y]]=x;
     28     else rc[fa[y]]=x;
     29     fa[y]=x; lc[x]=y;
     30     update(x); update(y);
     31 }
     32 void splay(int x,int s){
     33     int p;
     34     while(fa[x]!=s){
     35         p=fa[x];
     36         if(fa[p]==s){
     37             if(x==lc[p]) r_rotate(x);
     38             else l_rotate(x);
     39             break; 
     40         }
     41         if(x==lc[p]){
     42             if(p==lc[fa[p]]) r_rotate(p),r_rotate(x);
     43             else r_rotate(x),l_rotate(x);
     44         }
     45         else{
     46             if(p==rc[fa[p]]) l_rotate(p),l_rotate(x);
     47             else l_rotate(x),r_rotate(x);
     48         }
     49     }
     50     if(s==0) root=x;
     51     update(x);
     52 }
     53 int find(int v){//查找在这棵树中键值为v的节点 
     54     int x=root;
     55     while(x!=0){
     56         if(v<key[x]) x=lc[x];
     57         else if(v>key[x]) x=rc[x];
     58         else if(v==key[x]){
     59             splay(x,0);
     60             return x;
     61         }
     62     }
     63     return -1;
     64 }
     65 void New_node(int &x,int fath,int v){//建立新节点 
     66     x=++tot;
     67     lc[x]=rc[x]=0; siz[x]=1;
     68     fa[x]=fath;
     69     key[x]=v;
     70 }
     71 void insert(int v){//插入新节点 
     72     if(root==0){
     73         New_node(root,0,v);
     74         return ;
     75     }
     76     int p,x=root;
     77     while(x!=0){
     78         p=x;
     79         if(v<=key[x]) siz[x]++,x=lc[x];
     80         else siz[x]++,x=rc[x];
     81     }
     82     if(v<=key[p]) New_node(lc[p],p,v);
     83     else New_node(rc[p],p,v);
     84     splay(tot,0);
     85 }
     86 int getmax(int x){//找到以x为根的最大值 
     87     while(rc[x]!=0) x=rc[x];
     88     return x;
     89 }
     90 int getmin(int x){//找到以x为根的最小值 
     91     while(lc[x]!=0) x=lc[x];
     92     return x;
     93 }
     94 int getpre(int x){//找到节点x的前驱 
     95     splay(x,0);
     96     return getmax(lc[x]);
     97 }
     98 int getne(int x){//找到节点x的后继
     99     splay(x,0);
    100     return getmin(rc[x]);
    101 }
    102 void Delete(int v){//删除一个键值为v的节点 
    103     int x=find(v);
    104     splay(x,0);
    105     int pp=getpre(x),nn=getne(x);
    106     splay(pp,0);
    107     splay(nn,root);
    108     int y=fa[x];
    109     fa[x]=0;
    110     if(x==lc[y]) lc[y]=0;
    111     else lc[x]=0;
    112     update(x); update(y);
    113 }
    114 int rank(int rt,int v){//返回键值为v的节点的排名 
    115     if(rt==0) return 1;
    116     if(v<=key[rt]) return rank(lc[rt],v);
    117     else return siz[lc[rt]]+1+rank(rc[rt],v); 
    118 }
    119 int findkth(int x,int k){//在以x为根的树中找第 k大 
    120     if(siz[lc[x]]+1==k) return key[x];
    121     if(siz[lc[x]]+1>k) return findkth(lc[x],k);
    122     return findkth(rc[x],k-siz[lc[x]]-1);
    123 }
    124 
    125 int pred(int rt,int v){//返回比 v小的最大的数 
    126     if(rt==0) return v;
    127     if(v<=key[rt]) return pred(lc[rt],v);
    128     else{
    129         int ans=pred(rc[rt],v);
    130         if(ans==v) return key[rt]; 
    131         return ans;
    132     }
    133 }
    134 int succ(int rt,int v){//返回比 v大的最小的数 
    135     if(rt==0) return v;
    136     if(v>=key[rt]) return succ(rc[rt],v);
    137     else{
    138         int ans=succ(lc[rt],v);  
    139         if(ans==v) return key[rt];
    140         return ans;
    141     }
    142 }
    143 int main(){
    144     scanf("%d",&T);
    145     insert(-50000000); insert(50000000);
    146     while (T--){
    147         int kin,num;
    148         scanf("%d%d",&kin,&num);
    149         if(kin==1) insert(num);//插入 
    150         else if(kin==2) Delete(num);//删除(若有多个相同的数,只删除一个) 
    151         else if(kin==3) printf("%d
    ",rank(root,num)-1);//查询num数的排名(若有多个相同的数,因输出最小的排名)
    152         else if (kin==4) printf("%d
    ",findkth(root,num+1));//查询排名为x的数 
    153         else if (kin==5) printf("%d
    ",pred(root,num)); 
    154         else if (kin==6) printf("%d
    ",succ(root,num));
    155     }
    156     return 0;
    157 }
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cmath>
      5 #include<algorithm>
      6 #include<queue>
      7 #include<vector>
      8 using namespace std;
      9 const int maxn=200000;
     10 int key[maxn],lc[maxn],rc[maxn],fa[maxn],siz[maxn];
     11 int tot,root;
     12 int T;
     13 void update(int x){
     14     siz[x]=siz[lc[x]]+1+siz[rc[x]];
     15 }
     16 void r_rotate(int x){
     17     int y=fa[x];
     18     lc[y]=rc[x]; 
     19     if(rc[x]!=0) fa[rc[x]]=y; 
     20     fa[x]=fa[y];
     21     if(y==lc[fa[y]]) lc[fa[y]]=x;
     22     else rc[fa[y]]=x;
     23     fa[y]=x; rc[x]=y;
     24     update(x); update(y);
     25 }
     26 void l_rotate(int x){
     27     int y=fa[x];
     28     rc[y]=lc[x];
     29     if(lc[x]!=0) fa[lc[x]]=y;
     30     fa[x]=fa[y];
     31     if(y==lc[fa[y]]) lc[fa[y]]=x;
     32     else rc[fa[y]]=x;
     33     fa[y]=x; lc[x]=y;
     34     update(x); update(y);
     35 }
     36 void splay(int x,int s){
     37     int p;
     38     while(fa[x]!=s){
     39         p=fa[x];
     40         if(fa[p]==s){
     41             if(x==lc[p]) r_rotate(x);
     42             else l_rotate(x);
     43             break; 
     44         }
     45         if(x==lc[p]){
     46             if(p==lc[fa[p]]) r_rotate(p),r_rotate(x);
     47             else r_rotate(x),l_rotate(x);
     48         }
     49         else{
     50             if(p==rc[fa[p]]) l_rotate(p),l_rotate(x);
     51             else l_rotate(x),r_rotate(x);
     52         }
     53     }
     54     if(s==0) root=x;
     55     update(x);
     56 }
     57 int find(int v){//查找在这棵树中键值为v的节点 
     58     int x=root;
     59     while(x!=0){
     60         if(v<key[x]) x=lc[x];
     61         else if(v>key[x]) x=rc[x];
     62         else if(v==key[x]){
     63             splay(x,0);
     64             return x;
     65         }
     66     }
     67     return -1;
     68 }
     69 void New_node(int &x,int fath,int v){//建立新节点 
     70     x=++tot;
     71     lc[x]=rc[x]=0; siz[x]=1;
     72     fa[x]=fath;
     73     key[x]=v;
     74 }
     75 void insert(int v){//插入新节点 
     76     if(root==0){
     77         New_node(rc[0],0,v);
     78         root=tot;
     79         return ;
     80     }
     81     int p,x=root;
     82     while(x!=0){
     83         p=x;
     84         if(v<=key[x]) siz[x]++,x=lc[x];
     85         else siz[x]++,x=rc[x];
     86     }
     87     if(v<=key[p]) New_node(lc[p],p,v);
     88     else New_node(rc[p],p,v);
     89     splay(tot,0);
     90 }
     91 int getmax(int x){//找到以x为根的最大值 
     92     if(rc[x]!=0) return getmax(rc[x]);
     93     return x;
     94 }
     95 int getmin(int x){//找到以x为根的最小值 
     96        if(lc[x]!=0) return getmin(lc[x]);
     97     return x;
     98 }
     99 int getpre(int x){//找到节点x的前驱 
    100     splay(x,0);
    101     return getmax(lc[x]);
    102 }
    103 int getne(int x){//找到节点x的后继
    104     splay(x,0);
    105     return getmin(rc[x]);
    106 }
    107 void Delete(int v){
    108     int x=find(v);
    109     int pp=getmax(lc[x]);
    110     int nn=getmin(rc[x]);
    111     if(lc[x]==0||rc[x]==0){
    112         if(lc[x]==0&&rc[x]==0){
    113             root=0; rc[0]=0; 
    114             return ;
    115         }
    116         if(lc[x]==0){
    117             rc[0]=rc[x]; fa[rc[x]]=0; root=rc[x]; rc[x]=0;
    118             siz[x]=1;
    119             return ;
    120         }
    121         else{
    122             rc[0]=lc[x]; fa[lc[x]]=0; root=lc[x]; lc[x]=0;
    123             siz[x]=1;
    124             return ;
    125         }
    126     }
    127     splay(pp,0);
    128     splay(nn,root);
    129     fa[lc[nn]]=0; siz[lc[nn]]=1; lc[nn]=0;
    130     update(nn); update(pp);
    131 } 
    132 int rank(int rt,int v){//返回键值为v的节点的排名 
    133     if(rt==0) return 1;
    134     if(v<=key[rt]) return rank(lc[rt],v);
    135     else return siz[lc[rt]]+1+rank(rc[rt],v); 
    136 }
    137 int findkth(int x,int k){//在以x为根的树中找第 k大 
    138     if(siz[lc[x]]+1==k) return key[x];
    139     if(siz[lc[x]]+1>k) return findkth(lc[x],k);
    140     return findkth(rc[x],k-siz[lc[x]]-1);
    141 }
    142 
    143 int pred(int rt,int v){//返回比 v小的最大的数 
    144     if(rt==0)  return v;
    145     if(v<=key[rt]) return pred(lc[rt],v);
    146     else{
    147         int ans=pred(rc[rt],v);
    148         if(ans==v) return key[rt]; 
    149         return ans;
    150     }
    151 }
    152 int succ(int rt,int v){//返回比 v大的最小的数 
    153     if(rt==0) return v;
    154     if(v>=key[rt]) return succ(rc[rt],v);
    155     else{
    156         int ans=succ(lc[rt],v);  
    157         if(ans==v) return key[rt];
    158         return ans;
    159     }
    160 }
    161 int main(){
    162     freopen("phs.in","r",stdin);
    163     freopen("phs.out","w",stdout);
    164     scanf("%d",&T);
    165      while (T--){
    166         int kin,num;
    167         scanf("%d%d",&kin,&num);
    168         if(kin==1) 
    169             insert(num);//插入 
    170         else if(kin==2) 
    171             Delete(num);//删除(若有多个相同的数,只删除一个)
    172         else if(kin==3) 
    173             printf("%d
    ",rank(root,num));//查询num数的排名(若有多个相同的数,因输出最小的排名)
    174         else if (kin==4) 
    175             printf("%d
    ",findkth(root,num));//查询排名为x的数 
    176         else if (kin==5) 
    177             printf("%d
    ",pred(root,num)); 
    178         else if (kin==6) 
    179             printf("%d
    ",succ(root,num));
    180     }
    181     return 0;
    182 }
  • 相关阅读:
    SDUT 2143 图结构练习——最短路径 SPFA模板,方便以后用。。 Anti
    SDUT ACM 1002 Biorhythms 中国剩余定理 Anti
    nyist OJ 119 士兵杀敌(三) RMQ问题 Anti
    SDUT ACM 2157 Greatest Number Anti
    SDUT ACM 2622 最短路径 二维SPFA启蒙题。。 Anti
    二叉索引树 区间信息的维护与查询 Anti
    SDUT ACM 2600 子节点计数 Anti
    UVA 1428 Ping pong 二叉索引树标准用法 Anti
    2010圣诞Google首页效果
    Object
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/5184877.html
Copyright © 2011-2022 走看看