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 MB
Submit: 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

Sample Output

106465
84185
492737

HINT

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

 

2.每个数的数据范围:[-2e9,2e9]
posted @ 2018-08-14 20:37  wang9897  阅读(116)  评论(0编辑  收藏  举报