您的位置:首页 > 其它

[BZOJ 3224] [Tyvj 1728] 普通平衡树

2015-06-16 20:32 363 查看

3224: Tyvj 1728 普通平衡树

Time Limit: 10 SecMemory Limit: 128 MB

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]
【题解】
平衡树模板题目。

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int fa
,ch
[2],root,k
,ind=0,size
;
void zig(int x) {
int y=fa[x],z=fa[y];
fa[y]=x;
fa[x]=z;
ch[y][0]=ch[x][1],fa[ch[x][1]]=y,ch[x][1]=y;
if (y==ch[z][0]) ch[z][0]=x;
else ch[z][1]=x;
size[y]=size[ch[y][0]]+size[ch[y][1]]+1;
}
void zag(int x) {
int y=fa[x],z=fa[y];
fa[y]=x,fa[x]=z;
ch[y][1]=ch[x][0],fa[ch[x][0]]=y,ch[x][0]=y;
if (y==ch[z][0]) ch[z][0]=x;
else ch[z][1]=x;
size[y]=size[ch[y][0]]+size[ch[y][1]]+1;
}
void splay(int x,int s) {
while (fa[x]!=s) {
int y=fa[x],z=fa[y];
if (z==s) {
if (x==ch[y][0]) zig(x);
else zag(x);
break;
}
if (y==ch[z][0]) {
if (x==ch[y][0]) zig(y),zig(x);
else zag(x),zig(x);
}
else {
if (x==ch[y][1]) zag(y),zag(x);
else zig(x),zag(x);
}
}
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
if (s==0) root=x;
}
inline void newnode(int &x,int fax,int key) {
x=++ind;
ch[x][0]=ch[x][1]=0;
fa[x]=fax;
k[x]=key;
}
inline int search(int w) {
int p,x=root;
while(x) {
p=x;
if(k[x]>w) x=ch[x][0];
else x=ch[x][1];
}
return p;
}
inline void ins(int w){
if (root==0) {
newnode(root,0,w);
return ;
}
int i=search(w);
if(w<k[i]) newnode(ch[i][0],i,w);
else newnode(ch[i][1],i,w);
splay(ind,0);
}
int getsm(int w) {
int x=root,ans=ind+1;
while(x) {
if (k[x]>w) {x=ch[x][0];continue;}
if (k[x]<w) {x=ch[x][1];continue;}
if (k[x]==w) {
ans=x;
x=ch[x][0];
}
}
if (ans==ind+1) return -1;
return ans;
}
inline int getmax(int x) {while(ch[x][1]) x=ch[x][1]; return x;}
inline int getmin(int x) {while(ch[x][0]) x=ch[x][0]; return x;}
inline int getpre(int x) {return getmax(ch[root][0]);}
inline int getnext(int x) {return getmin(ch[root][1]);}
inline void del(int w) {
int x=getsm(w);
splay(x,0);
int pp=getpre(x),nn=getnext(x);
splay(pp,0);splay(nn,root);
int y=fa[x];
fa[x]=0;
if(x==ch[y][0]) ch[y][0]=0;
else ch[x][0]=0;
size[y]=size[ch[y][0]]+size[ch[y][1]]+1;
size[root]=size[ch[root][0]]+size[ch[root][1]]+1;
}
inline int ffind(int w) {
int x=getsm(w);
splay(x,0);
return size[ch[x][0]];
}
int findkth(int x,int kth) {
int s=size[ch[x][0]];
if(kth==s+1) return k[x];
if(s>=kth) return findkth(ch[x][0],kth);
else return findkth(ch[x][1],kth-s-1);
}
int getp(int w) {
int y=getsm(w);
ins(w);
if(y!=-1) splay(y,0);
int ans=getmax(ch[root][0]);
del(w);
return k[ans];
}
int getn(int w) {
ins(w);
int ans=getmin(ch[root][1]);
del(w);
return k[ans];
}
int main() {
int q;
root=0;
ins(-5000000);ins(5000000);
scanf("%d",&q);
while (q--) {
int x,k;
scanf("%d%d",&x,&k);
if (x==1) ins(k);
else if (x==2) del(k);
else if (x==3) printf("%d\n",ffind(k));
else if (x==4) printf("%d\n",findkth(root,k+1));
else if (x==5) printf("%d\n",getp(k));
else if (x==6) printf("%d\n",getn(k));
}
return 0;
}


View Code
还是习惯分开来写Zig-Zag
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: