zoukankan      html  css  js  c++  java
  • 伸展树基础(Splay)

    3224: Tyvj 1728 普通平衡树

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 3948  Solved: 1627
    [Submit][Status][Discuss]

    Description

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

    Input

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

    Output

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

    Sample Input

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

    Sample Output

    106465
    84185
    492737

    HINT

    1.n的数据范围:n<=100000

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

      

      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 }
  • 相关阅读:
    ArcGIS Pro获得一个要素图层一种方法
    ArcGIS Pro layout clone
    ActiveMapViewChanged和选择变化
    ArcGIS Pro 改变栅格的数据源
    ArcGIS Pro自定义图标
    Windows Server 2016 路由和远程访问
    IIS应用程序池_缓存回收
    asp.net RSA密钥之C#格式与Java格式转换(PEM格式)
    MD5和Hash
    C# list与数组的转换
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/4626599.html
Copyright © 2011-2022 走看看