• COJS:1829. [Tyvj 1728]普通平衡树


                    ★★★   输入文件:phs.in   输出文件:phs.out   简单对比
                      时间限制:1 s   内存限制:128 MB

    【题目描述】

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
    1. 插入x数
    2. 删除x数(若有多个相同的数,因只删除一个)
    3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
    4. 查询排名为x的数
    5. 求x的前驱(前驱定义为小于x,且最大的数)
    6. 求x的后继(后继定义为大于x,且最小的数)

    【输入格式】

    第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

    【输出格式】

    对于操作3,4,5,6每行输出一个数,表示对应答案

    【样例输入】

    10
    1 106465
    4 1
    1 317721
    1 460929
    1 644985
    1 84185
    1 89851
    6 81968
    1 492737
    5 493598

    【样例输出】

    106465
    84185
    492737

    【提示】

    1.n的数据范围:n<=100000
    2.每个数的数据范围:[-1e7,1e7]

      SBT版的:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=100010;
      4 int root,tot,N;
      5 int key[maxn],siz[maxn],lc[maxn],rc[maxn];
      6 void r_rotate(int &rt){
      7     int k=lc[rt];
      8     lc[rt]=rc[k];
      9     rc[k]=rt;
     10     siz[k]=siz[rt];
     11     siz[rt]=siz[lc[rt]]+siz[rc[rt]]+1;
     12     rt=k;
     13 }  
     14 void l_rotate(int &rt){
     15     int k=rc[rt];
     16     rc[rt]=lc[k];
     17     lc[k]=rt;
     18     siz[k]=siz[rt];
     19     siz[rt]=siz[lc[rt]]+siz[rc[rt]]+1;
     20     rt=k;
     21 }
     22 void MAINTAIN(int &rt,bool flag){
     23     if(flag==false){//rt的左子树的某子树>rt的右子树 
     24         if(siz[lc[lc[rt]]]>siz[rc[rt]]) r_rotate(rt);//如果rt的左孩子的左孩子>rt的右孩子,rt右旋 
     25         else if(siz[rc[lc[rt]]]>siz[rc[rt]]){//如果rt的左孩子L的右孩子B > rt的右孩子R: 
     26             l_rotate(lc[rt]);//先让rt的左孩子左旋,使rt的左子树变成以B为根 
     27             r_rotate(rt);//再右旋再变成以B为根 
     28         }
     29         else return;//平衡 
     30     }
     31     else{//rt的右子树的某子树>rt的左子树 
     32         if(siz[rc[rc[rt]]]>siz[lc[rt]]) l_rotate(rt);
     33         else if(siz[lc[rc[rt]]]>siz[lc[rt]]){
     34             r_rotate(rc[rt]);
     35             l_rotate(rt);
     36         }
     37         else return;
     38     }
     39     MAINTAIN(lc[rt],0); MAINTAIN(rc[rt],1);//检查是否满足平衡 
     40     MAINTAIN(rt,1); MAINTAIN(rt,0);
     41 }
     42 void insert(int &rt,int v){
     43     if(rt==0){//找到合适的位置插入 
     44         rt=++tot; 
     45         key[rt]=v;
     46         lc[rt]=rc[rt]=0; siz[rt]=1;
     47         return ;
     48     }
     49     siz[rt]++;
     50     if(v<=key[rt]) insert(lc[rt],v);
     51     else insert(rc[rt],v);
     52     MAINTAIN(rt,v>key[rt]);//调整树结构 
     53 }
     54 int Delete(int &rt,int v){
     55     int ans;
     56     siz[rt]--;
     57     if(v==key[rt]||(v<key[rt]&&lc[rt]==0)||(v>key[rt]&&rc[rt]==0)){
     58         ans=key[rt];
     59         if(lc[rt]==0||rc[rt]==0) rt=lc[rt]+rc[rt];//没有左子树或者右子树,直接利用&操作,相当于直接以子树接到上个节点 
     60         else key[rt]=Delete(lc[rt],key[rt]+1);//返回左子树中的最大值,然后替换当前的rt,相当于删掉当前节点,用左子树中最大值放在这个位置来代替
     61         return ans;
     62     }
     63     if(v<key[rt]) ans=Delete(lc[rt],v);
     64     else ans=Delete(rc[rt],v);
     65     return ans;
     66 }
     67 bool find(int &rt,int v){//查找是否有 key值为 v的节点 
     68     if(rt==0) return false;
     69     else if(v==key[rt]) return true;
     70     else if(v<key[rt]) return find(lc[rt],v);
     71     else if(v>key[rt]) return find(rc[rt],v);
     72 }
     73 int rank(int &rt,int v){//询问排名 
     74     if(rt==0) return 1;
     75     if(v<=key[rt]) return rank(lc[rt],v);
     76     else return siz[lc[rt]]+1+rank(rc[rt],v);
     77 }
     78 /*
     79 如果元素唯一的话,可以这么写: 
     80 int rank(int &rt,int v){
     81     if(rt==0) return 1;
     82     if(v==key[rt]) return siz[lc[rt]]+1;
     83     if(v<key[rt]) return rank(lc[rt],v);
     84     return siz[lc[rt]]+1+rank(rc[rt],v);
     85 }
     86 但此题不行 
     87 */
     88 int select(int &rt,int k){//返回在v位置上的节点,可以改造成取大和取小函数 
     89     if(k==siz[lc[rt]]+1) return key[rt];
     90     if(k<=siz[lc[rt]]) return select(lc[rt],k);
     91     else return select(rc[rt],k-1-siz[lc[rt]]);
     92 }
     93 int pred(int &rt,int v){//返回比 v小的最大的数 
     94     if(rt==0) return v;//要求是比v小,返回v的意思是没找到 
     95     if(v<=key[rt]) return pred(lc[rt],v);//key[rt]>v 必然要往更小的方向,即rt的左子树 
     96     else{//此时 key[rt]<v,而rt的右子树的key值都大于key[rt] 
     97         int ans=pred(rc[rt],v);
     98         if(ans==v) return key[rt];//返回v表示rt的右子树中的key都比v大,返回key[rt] 
     99         return ans;
    100     }
    101 }
    102 int succ(int &rt,int v){//返回比v大的最小的数 
    103     if(rt==0) return v;
    104     if(v>=key[rt]) return succ(rc[rt],v);
    105     else{
    106         int ans=succ(lc[rt],v);
    107         if(ans==v) return key[rt];
    108         return ans;
    109     }
    110 }
    111 void inorder(int rt){//输出中序遍历 
    112     if(rt!=0){
    113         inorder(lc[rt]);
    114         cout<<key[rt]<<" ";
    115         inorder(rc[rt]);
    116     }
    117 }
    118 int main(){    
    119     siz[0]=root=tot=0;
    120     scanf("%d",&N);
    121     for(int i=1,kin,num;i<=N;i++){
    122         scanf("%d%d",&kin,&num);
    123         if(kin==1) insert(root,num);
    124         else if(kin==2) Delete(root,num);
    125         else if(kin==3) printf("%d
    ",rank(root,num));
    126         else if(kin==4) printf("%d
    ",select(root,num));
    127         else if(kin==5) printf("%d
    ",pred(root,num));
    128         else if(kin==6) printf("%d
    ",succ(root,num));
    129     }
    130     return 0;
    131 }

          无注释版的:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=100010;
      4 int root,tot,N;
      5 int key[maxn],siz[maxn],lc[maxn],rc[maxn];
      6 void r_rotate(int &rt){
      7     int k=lc[rt];
      8     lc[rt]=rc[k];
      9     rc[k]=rt;
     10     siz[k]=siz[rt];
     11     siz[rt]=siz[lc[rt]]+siz[rc[rt]]+1;
     12     rt=k;
     13 }  
     14 void l_rotate(int &rt){
     15     int k=rc[rt];
     16     rc[rt]=lc[k];
     17     lc[k]=rt;
     18     siz[k]=siz[rt];
     19     siz[rt]=siz[lc[rt]]+siz[rc[rt]]+1;
     20     rt=k;
     21 }
     22 void MAINTAIN(int &rt,bool flag){
     23     if(flag==false){
     24         if(siz[lc[lc[rt]]]>siz[rc[rt]]) r_rotate(rt);
     25         else if(siz[rc[lc[rt]]]>siz[rc[rt]]){
     26             l_rotate(lc[rt]);
     27             r_rotate(rt);
     28         }
     29         else return;
     30     }
     31     else{
     32         if(siz[rc[rc[rt]]]>siz[lc[rt]]) l_rotate(rt);
     33         else if(siz[lc[rc[rt]]]>siz[lc[rt]]){
     34             r_rotate(rc[rt]);
     35             l_rotate(rt);
     36         }
     37         else return;
     38     }
     39     MAINTAIN(lc[rt],0); MAINTAIN(rc[rt],1);
     40     MAINTAIN(rt,1); MAINTAIN(rt,0);
     41 }
     42 void insert(int &rt,int v){
     43     if(rt==0){
     44         rt=++tot; 
     45         key[rt]=v;
     46         lc[rt]=rc[rt]=0; siz[rt]=1;
     47         return ;
     48     }
     49     siz[rt]++;
     50     if(v<=key[rt]) insert(lc[rt],v);
     51     else insert(rc[rt],v);
     52     MAINTAIN(rt,v>key[rt]);
     53 }
     54 int Delete(int &rt,int v){
     55     int ans;
     56     siz[rt]--;
     57     if(v==key[rt]||(v<key[rt]&&lc[rt]==0)||(v>key[rt]&&rc[rt]==0)){
     58         ans=key[rt];
     59         if(lc[rt]==0||rc[rt]==0) rt=lc[rt]+rc[rt];
     60         else key[rt]=Delete(lc[rt],key[rt]+1);
     61         return ans;
     62     }
     63     if(v<key[rt]) ans=Delete(lc[rt],v);
     64     else ans=Delete(rc[rt],v);
     65     return ans;
     66 }
     67 bool find(int &rt,int v){
     68     if(rt==0) return false;
     69     else if(v==key[rt]) return true;
     70     else if(v<key[rt]) return find(lc[rt],v);
     71     else if(v>key[rt]) return find(rc[rt],v);
     72 }
     73 int rank(int &rt,int v){
     74     if(rt==0) return 1;
     75     if(v<=key[rt]) return rank(lc[rt],v);
     76     else return siz[lc[rt]]+1+rank(rc[rt],v);
     77 }
     78 int select(int &rt,int k){
     79     if(k==siz[lc[rt]]+1) return key[rt];
     80     if(k<=siz[lc[rt]]) return select(lc[rt],k);
     81     else return select(rc[rt],k-1-siz[lc[rt]]);
     82 }
     83 int pred(int &rt,int v){
     84     if(rt==0) return v;
     85     if(v<=key[rt]) return pred(lc[rt],v);
     86     else{
     87         int ans=pred(rc[rt],v);
     88         if(ans==v) return key[rt];
     89         return ans;
     90     }
     91 }
     92 int succ(int &rt,int v){
     93     if(rt==0) return v;
     94     if(v>=key[rt]) return succ(rc[rt],v);
     95     else{
     96         int ans=succ(lc[rt],v);
     97         if(ans==v) return key[rt];
     98         return ans;
     99     }
    100 }
    101 void inorder(int rt){
    102     if(rt!=0){
    103         inorder(lc[rt]);
    104         cout<<key[rt]<<" ";
    105         inorder(rc[rt]);
    106     }
    107 }
    108 int main(){    
    109     siz[0]=root=tot=0;
    110     scanf("%d",&N);
    111     for(int i=1,kin,num;i<=N;i++){
    112         scanf("%d%d",&kin,&num);
    113         if(kin==1) insert(root,num);
    114         else if(kin==2) Delete(root,num);
    115         else if(kin==3) printf("%d
    ",rank(root,num));
    116         else if(kin==4) printf("%d
    ",select(root,num));
    117         else if(kin==5) printf("%d
    ",pred(root,num));
    118         else if(kin==6) printf("%d
    ",succ(root,num));
    119     }
    120     return 0;
    121 }

       Splay版的:

      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 }

      vector版的:

     1 #include<cstdio>
     2 #include<vector>
     3 #include<algorithm>
     4 using namespace std;
     5 const int INF=10000000;
     6 int n;
     7 vector<int> tree;
     8 int find(int x){
     9     return lower_bound(tree.begin(),tree.end(),x)-tree.begin()+1;
    10 }
    11 int main(){
    12     scanf("%d",&n);
    13     tree.reserve(200000);
    14     for(int i=1,kin,x;i<=n;i++){
    15         scanf("%d%d",&kin,&x);
    16         if(kin==1) tree.insert(upper_bound(tree.begin(),tree.end(),x),x);
    17         else if(kin==2) tree.erase(lower_bound(tree.begin(),tree.end(),x));
    18         else if(kin==3) printf("%d
    ",find(x));
    19         else if(kin==4) printf("%d
    ",tree[x-1]);
    20         else if(kin==5) printf("%d
    ",*--lower_bound(tree.begin(),tree.end(),x));
    21         else if(kin==6) printf("%d
    ",*upper_bound(tree.begin(),tree.end(),x));
    22     }
    23     return 0;
    24 }
  • 相关阅读:
    Java之JVM调优案例分析与实战(4)
    Qt浅谈之四十九俄罗斯方块(代码来自网络)
    自作聪明的开发
    Visual Studio 连接 SQL Server 的connectionStringz和
    删除反复行SQL举例
    一起学android之怎样设置TextView中不同字段的字体颜色(22)
    A008-drawable资源
    android 自己定义组件随着手指自己主动画圆
    一个简单的HTML5摇一摇实例
    关于事件的传递机制。
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/5094706.html
Copyright © 2020-2023  润新知