[Splay模板大全]Tyvj 1728 普通平衡树

Description

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

Input

第一行为n,表示操作的个数
下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]

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

我本来是不想先用这道题的,但是想想板子的重要性,我还是选择了这道题,此题仅仅是存板子

像这种真的就是套板子的题目,真的没有什么好讲的

这个板子不代表所有(还有恶心的区间操作)

代码:

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 using namespace std;
  5 #define MAXN 1000000
  6 int ch[MAXN][2],f[MAXN],size[MAXN],cnt[MAXN],key[MAXN];
  7 int sz,root;
  8 inline bool get(int x)
  9 {
 10     return ch[f[x]][1]==x;
 11 }
 12 void update(int x)
 13 {
 14     if (x){
 15         size[x]=cnt[x];
 16         if (ch[x][0]) size[x]+=size[ch[x][0]];
 17         if (ch[x][1]) size[x]+=size[ch[x][1]];
 18     }
 19 }
 20 void move(int now)
 21 {
 22     int fa=f[now],cnt=get(now),faa=f[fa];
 23     if(fa==root)root=now;
 24     else if(faa)ch[faa][get(fa)]=now;
 25     ch[fa][cnt]=ch[now][cnt^1];
 26     f[ch[now][cnt^1]]=fa;
 27     ch[now][cnt^1]=fa;
 28     f[fa]=now;
 29     f[now]=faa;
 30     update(fa),update(now);
 31 }
 32 void splay(int x,int &k)
 33 {
 34     int y,z;
 35     while(x!=k)
 36     {
 37         y=f[x],z=f[y];
 38         if(y!=k)
 39         {
 40             if((ch[y][0]==ch[z][0])^(ch[y][1]==ch[z][1]))move(y);
 41             else move(x);
 42         }
 43         move(x);
 44     }
 45 }
 46 int find(int x)
 47 {
 48     int now=root,ans=0;
 49     while(1)
 50     {
 51         if(x<key[now])
 52             now=ch[now][0];
 53         else
 54         {
 55             ans+=(ch[now][0]?size[ch[now][0]]:0);
 56             if(x==key[now]){splay(now,root);return ans+1;}
 57             ans+=cnt[now];
 58             now=ch[now][1];
 59         }
 60     }
 61 }
 62 int findx(int x)
 63 {
 64      int now=root;
 65      while(1)
 66      {
 67         if(ch[now][0]&&x<=size[ch[now][0]])
 68             now=ch[now][0];
 69         else
 70         {
 71             int w=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];
 72             if (x<=w){return key[now];}
 73             x-=w;now=ch[now][1];
 74         }
 75      }
 76 }
 77 void inss(int m)
 78 {
 79     if(root==0){sz++;root=sz;key[sz]=m;cnt[sz]=1,size[sz]=1;return ;}
 80     int now=root,fa=0;
 81     while(1){
 82         if (m==key[now]){
 83             cnt[now]++; update(now); update(fa); splay(now,root); break;
 84         }
 85         fa=now;
 86         now=ch[now][key[now]<m];
 87         if (now==0){
 88             sz++;
 89             ch[sz][0]=ch[sz][1]=0;
 90             f[sz]=fa;
 91             size[sz]=cnt[sz]=1;
 92             ch[fa][key[fa]<m]=sz;
 93             key[sz]=m;
 94             update(fa);
 95             splay(sz,root);
 96             break;
 97         }
 98     }
 99 }
100 int pre()
101 {
102     int now=ch[root][0];
103     while (ch[now][1])now=ch[now][1];
104     return now;
105 }
106 int next()
107 {
108     int now=ch[root][1];
109     while (ch[now][0])now=ch[now][0];
110     return now;
111 }
112 void deel(int x)
113 {
114     int aa=find(x);
115     if(cnt[root]>1){cnt[root]--;return ;}
116     if (!ch[root][0]&&!ch[root][1]){root=0;return;}
117     if(ch[root][0]&&!ch[root][1]){root=ch[root][0];f[root]=0;return ;}
118     if(ch[root][1]&&!ch[root][0]){root=ch[root][1];f[root]=0;return ;}
119     int old=pre();int rt=root;
120     splay(old,root);
121     f[ch[rt][1]]=root;
122     ch[root][1]=ch[rt][1];
123     update(root);
124 }
125 int main(){
126     int n,opt,x;
127     scanf("%d",&n);
128     for (int i=1;i<=n;++i){
129         scanf("%d%d",&opt,&x);
130         switch(opt){
131             case 1: inss(x); break;
132             case 2: deel(x); break;
133             case 3: printf("%d\n",find(x)); break;
134             case 4: printf("%d\n",findx(x)); break;
135             case 5: inss(x);printf("%d\n",key[pre()]);deel(x);break;
136             case 6: inss(x); printf("%d\n",key[next()]);deel(x);break;
137         }
138     }
139 }

猜你喜欢

转载自www.cnblogs.com/lcxer/p/9441592.html
今日推荐