BZOJ3224: Tyvj 1728 普通平衡树
题解:权值平衡树 按题意模拟即可
#include <bits/stdc++.h>
#define rt ch[ch[root][1]][0]
const int MAXN=1e5+10;
const int inf=1e9+10;
using namespace std;
int ch[MAXN][2],root,pre[MAXN],size[MAXN],key[MAXN],cnt,maxn[MAXN];
void up(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+1;maxn[x]=max(max(maxn[ch[x][0]],maxn[ch[x][1]]),key[x]);}
void Treavel(int x)
{
if(x)
{
// cout<<x<<endl;
Treavel(ch[x][0]);
printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d\n",x,ch[x][0],ch[x][1],pre[x],size[x],key[x]);
Treavel(ch[x][1]);
}
}
void debug(int rp)
{
printf("root:%d\n",rp);
Treavel(rp);
}
void newnode(int &x,int fa,int vul){
x=++cnt;ch[x][0]=ch[x][1]=0;pre[x]=fa;size[x]=1;maxn[x]=key[x]=vul;
}
void rotate(int x,int kind){
int y=pre[x];
ch[y][!kind]=ch[x][kind];pre[ch[x][kind]]=y;
if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
pre[x]=pre[y];ch[x][kind]=y;pre[y]=x;
up(y);
}
void splay(int x,int goal){
while(pre[x]!=goal){
if(pre[pre[x]]==goal) rotate(x,ch[pre[x]][0]==x);
else{
int y=pre[x];int kind=ch[pre[y]][0]==y;
if(ch[y][kind]==x) rotate(x,!kind),rotate(x,kind);
else rotate(y,kind),rotate(x,kind);
}
}
if(goal==0) root=x;
up(x);
}
int minn;
int find1(int x,int vul){
//if(!x) return ;
if(key[x]==vul){
if(maxn[ch[x][0]]==vul) return find1(ch[x][0],vul);
else return x;
}
else if(key[x]<vul) return find1(ch[x][1],vul);
else return find1(ch[x][0],vul);
}
int find2(int x,int siz){
if(siz==size[ch[x][0]]+1) return x;
else if(siz<=size[ch[x][0]]) return find2(ch[x][0],siz);
else return find2(ch[x][1],siz-size[ch[x][0]]-1);
}
//操作
void insert(int &x,int vul,int fa){
if(x==0){newnode(x,fa,vul);return ;}
if(key[x]>vul) insert(ch[x][0],vul,x);
else insert(ch[x][1],vul,x);
up(x);
}
void erase(int vul){
splay(find1(root,vul),0);int t=size[ch[root][0]]+1;
splay(find2(root,t-1),0);splay(find2(root,t+1),root);
pre[rt]=0;rt=0;up(ch[root][1]);up(root);
}
void rank1(int vul){
splay(find1(root,vul),0);
printf("%d\n",size[ch[root][0]]);
}
void frank(int x){
printf("%d\n",key[find2(root,x+1)]);
}
int ans;
void vul_pre(int x,int vul){
if(!x) return ;
if(key[x]>=vul) vul_pre(ch[x][0],vul);
else{
int t=vul-key[x];
if(t<=vul-ans) ans=key[x],vul_pre(ch[x][1],vul);
else vul_pre(ch[x][1],vul);
}
}
void vul_last(int x,int vul){
if(!x) return ;
if(key[x]<=vul) vul_last(ch[x][1],vul);
else{
int t=key[x]-vul;
if(t<=ans-vul) ans=key[x],vul_last(ch[x][0],vul);
else vul_last(ch[x][0],vul);
}
}
void inte(){
cnt=0;
newnode(root,0,-1*inf);
newnode(ch[root][1],root,inf);
}
int main(){
//freopen("1.in","r",stdin);
//freopen("3.out","w",stdout);
int n;scanf("%d",&n);
int op,vul;
inte();
for(int i=1;i<=n;i++){
scanf("%d%d",&op,&vul);
if(op==1) insert(root,vul,0);
else if(op==2) erase(vul);
else if(op==3) rank1(vul);
else if(op==4) frank(vul);
else if(op==5){
ans=-1*inf;vul_pre(root,vul);
printf("%d\n",ans);
}
else{
ans=inf;vul_last(root,vul);
printf("%d\n",ans);
}
}
return 0;
}
3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 21834 Solved: 9749
[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
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
84185
492737
HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]

浙公网安备 33010602011771号