您的位置:首页 > 其它

HYSBZ-3224:Tyvj 1728 普通平衡树(splay结构体,无插入求前驱后继)

2017-09-06 09:41 597 查看

3224: Tyvj 1728 普通平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 15555  Solved: 6769

[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.每个数的数据范围:[-2e9,2e9]

思路:splay基本操作。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct SPLAY
{
int val;
int num,size;
int f,l,r;
}a[200000];
int root,size;
void show(int k) //额。。。调试用的
{
if(k==-1)return;
printf("a[%d] father=%d val=%d num=%d size=%d l=%d r=%d\n",k,a[k].f,a[k].val,a[k].num,a[k].size,a[k].l,a[k].r);
show(a[k].l);
show(a[k].r);
}
void maintain(int k)//更新数据
{
if(k==-1)return;
a[k].size=a[k].num;
if(a[k].l!=-1)a[k].size+=a[a[k].l].size;
if(a[k].r!=-1)a[k].size+=a[a[k].r].size;
}
void right_rotate(int k)//右旋
{
int p=a[k].f;
a[k].f=a[p].f;
if(a[p].f!=-1)
{
if(a[a[p].f].l==p)a[a[p].f].l=k;
else a[a[p].f].r=k;
}
else root=k;
a[p].l=a[k].r;
if(a[k].r!=-1)a[a[k].r].f=p;
a[k].r=p;
a[p].f=k;
maintain(p);//旋转后更新数据,顺序不能反
maintain(k);
}
void left_rotate(int k)//左旋
{
int p=a[k].f;
a[k].f=a[p].f;
if(a[p].f!=-1)
{
if(a[a[p].f].l==p)a[a[p].f].l=k;
else a[a[p].f].r=k;
}
else root=k;
a[p].r=a[k].l;
if(a[k].l!=-1)a[a[k].l].f=p;
a[k].l=p;
a[p].f=k;
maintain(p);
maintain(k);
}
void splay(long long k,long long f)
{
while(a[k].f!=f)
{
long long p=a[k].f;
if(a[p].f==f)
{
if(a[p].l==k)right_rotate(k);
else left_rotate(k);
}
else
{
long long ff=a[p].f;
if(p==a[ff].l&&k==a[p].l)right_rotate(p),right_rotate(k);
if(p==a[ff].l&&k==a[p].r)left_rotate(k),right_rotate(k);
if(p==a[ff].r&&k==a[p].r)left_rotate(p),left_rotate(k);
if(p==a[ff].r&&k==a[p].l)right_rotate(k),left_rotate(k);
}
}
}
void insert(int k,int val)//插入
{
if(k<0) //第一次插入root=-1
{
a[size].val=val;
a[size].l=a[size].r=-1;
a[size].f=-1;
a[size].size=a[size].num=1;
root=size;
splay(size,-1);
size++;
return;
}
if(val<a[k].val)
{
if(a[k].l!=-1)insert(a[k].l,val);
else
{
a[size].val=val;
a[size].size=a[size].num=1;
a[size].l=a[size].r=-1;
a[size].f=k;
a[k].l=size;
splay(size,-1);
size++;
}
}
else if(val>a[k].val)
{
if(a[k].r!=-1)insert(a[k].r,val);
else
{
a[size].val=val;
a[size].size=a[size].num=1;
a[size].l=a[size].r=-1;
a[size].f=k;
a[k].r=size;
splay(size,-1);
size++;
}
}
else a[k].num++,a[k].size++,splay(k,-1);//碰到相同的数
maintain(k);
}
int search(int k,int x)//查询x的排名
{
if(a[k].val>x)
{
if(a[k].l!=-1)return search(a[k].l,x);
}
else if(a[k].val<x)
{
if(a[k].r!=-1)return search(a[k].r,x);
}
else
{
splay(k,-1);//先把它旋转到根节点
maintain(k);
return a[k].size-a[k].num+1-(a[k].r==-1?0:a[a[k].r].size);
//取最小排名,去掉重复的数和右边比它大的数
//(早上精神状态不怎么好,这里忘记处理细节,WA了好几发。。)
}
}
int ask(int x)//查找第x小的数
{
int k=root;
while(1)
{
if(a[k].l!=-1&&x<=a[a[k].l].size)k=a[k].l;
else
{
int temp=(a[k].l==-1?0:a[a[k].l].size)+a[k].num;
if(x<=temp)return a[k].val;
x-=temp;
k=a[k].r;
}
}
}
int askpre(int k,int val) //求前驱
{
if(a[k].val>val)
{
if(a[k].l==-1)
{
long long p=a[k].f;
while(p!=-1&&k==a[p].l)k=p,p=a[p].f;
return p;
}
return askpre(a[k].l,val);
}
else if(a[k].val<val)
{
if(a[k].r==-1)return k;
return askpre(a[k].r,val);
}
if(a[k].l==-1)
{
long long p=a[k].f;
while(p!=-1&&k==a[p].l)k=p,p=a[p].f;
return p;
}
k=a[k].l;
while(a[k].r!=-1)k=a[k].r;
return k;
}
int asknex(int k,int val) //求后继
{
if(val<a[k].val)
{
if(a[k].l==-1)return k;
return asknex(a[k].l,val);
}
else if(val>a[k].val)
{
if(a[k].r==-1)
{
int p = a[k].f;
while( p!=-1&&k==a[p].r)k = p,p = a[p].f;
return p;
}
return asknex(a[k].r,val);
}
if(a[k].r==-1)
{
int p = a[k].f;
while( p!=-1&& k == a[p].r )k = p,p = a[p].f;
return p;
}
k=a[k].r;
while( a[k].l!=-1 )k = a[k].l;
return k;
}
void Delete(int val) //单点删除
{
long long pre=askpre(root,val);
long long nex=asknex(root,val);
if(pre!=-1&&nex!=-1)
{
splay(pre,-1);
splay(nex,pre);
if(a[a[nex].l].num>1)a[a[nex].l].num--;
else a[nex].l=-1;
maintain(a[nex].l); //删除后及时更新数据,顺序不能反
maintain(nex);
maintain(pre);
}
else if(pre!=-1&&nex==-1)
{
splay(pre,-1);
if(a[pre].r!=-1&&a[a[pre].r].val==val)
{
if(a[a[pre].r].num>1)a[a[pre].r].num--;
else a[pre].r=-1;
}
maintain(a[pre].r);
maintain(pre);
}
else if(pre==-1&&nex!=-1)
{
splay(nex,-1);
if(a[nex].l!=-1&&a[a[nex].l].val==val)
{
if(a[a[nex].l].num>1)a[a[nex].l].num--;
else a[nex].l=-1;
}
maintain(a[nex].l);
maintain(nex);
}
}
int main()
{
int T;cin>>T;
root=-1,size=0;
while(T--)
{
int x,op;
scanf("%d%d",&op,&x);
if(op==1)insert(root,x);
if(op==2)Delete(x);
if(op==3)printf("%d\n",search(root,x));
if(op==4)printf("%d\n",ask(x));
if(op==5)printf("%d\n",a[askpre(root,x)].val);
if(op==6)printf("%d\n",a[asknex(root,x)].val);
//show(root);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: