• 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 }
  • 相关阅读:
    jdbc连接池中c3p0的配置文件的详解以及在在java中如何使用
    idea导入myeclipes项目、运行项目
    java中身份证号和的银行卡的深度校验
    springBoot的搭建使用记录
    java分模块项目在idea中使用maven打包失败(ps:maven常用到的命令)
    js获取当前页面相关信息
    mybatis使用中的记录
    tomcat服务的启动与隐藏启动(win)
    cmd命令关闭占用程序的端口
    ping端口是否开放(windows,macos,linux)
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/5184877.html
Copyright © 2020-2023  润新知