【Splay】bzoj3224 Tyvj 1728 普通平衡树

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 1000000
#define INF 2147483647
int n,fa[maxn],val[maxn],c[maxn][2],root,tot,siz[maxn],cnt[maxn];
void Maintain(int x)
{
    siz[x]=siz[c[x][0]]+siz[c[x][1]]+cnt[x];
}
void NewNode(int &x,int Fa,int key)
{
    x=++tot;
    fa[x]=Fa;
    c[x][0]=c[x][1]=0;
    val[x]=key;
    siz[x]=cnt[x]=1;
}
void Rotate(int x,bool flag)
{
    int y=fa[x];
    c[y][!flag]=c[x][flag];
    fa[c[x][flag]]=y;
    if(fa[y]){
        c[fa[y]][c[fa[y]][1]==y]=x;
    }
    fa[x]=fa[y];
    c[x][flag]=y;
    fa[y]=x;
    Maintain(y);
}
void Splay(int x,int goal)
{
    if(!x){
        return;
    }
    int y;
    while((y=fa[x])!=goal){
        if(fa[y]==goal){
            Rotate(x,c[y][0]==x);
        }
        else{
            if((c[y][0]==x)==(c[fa[y]][0]==y)){
                Rotate(y,c[fa[y]][0]==y);
            }
            else{
                Rotate(x,c[y][0]==x);
                y=fa[x];
            }
            Rotate(x,c[y][0]==x);
        }
    }
    Maintain(x);
    if(!goal){
        root=x;
    }
}
int Find(int key,int x=root)
{
    while(c[x][val[x]<key]){
        if(val[x]==key){
            return x;
        }
        x=c[x][val[x]<key];
    }
    return x;
}
void Insert(int key)
{
    if(!root){
        NewNode(root,0,key);
        return;
    }
    int x=Find(key);
    if(val[x]==key){
        ++cnt[x];
        Splay(x,0);
        return;
    }
    NewNode(c[x][val[x]<key],x,key);
    Splay(c[x][val[x]<key],0);
}
int Findmax(int x=root)
{
    while(c[x][1]){
        x=c[x][1];
    }
    return x;
}
int Findmin(int x=root)
{
    while(c[x][0]){
        x=c[x][0];
    }
    return x;
}
void Delete(int key)
{
    int x=Find(key);
    Splay(x,0);
    if(val[x]==key){
        --cnt[x];
        if(!cnt[x]){
            if(!c[x][0]&&!c[x][1]){
                root=0;
            }
            else if(!c[x][0]||!c[x][1]){
                fa[c[x][c[x][0]==0]]=0;
                root=c[x][c[x][0]==0];
            }
            else{
                int y=Findmax(c[x][0]);
                Splay(y,root);
                c[y][1]=c[root][1];
                fa[c[root][1]]=y;
                root=y;
                fa[root]=0;
                Maintain(root);
            }
        }
        else{
            Maintain(x);
        }
    }
}
int Rank(int key)
{
    int x=Find(key);
    Splay(x,0);
    return siz[c[x][0]]+1;
}
int Kth(int K,int x=root)
{
    while(1){
        int Siz0=siz[c[x][0]];
        if(K<=Siz0){
            x=c[x][0];
        }
        else if(K<=Siz0+cnt[x]){
            return val[x];
        }
        else{
            K-=(Siz0+cnt[x]);
            x=c[x][1];
        }
    }
}
int GetPre(int key)
{
    int x=Find(key);
    if(val[x]==key){
        Splay(x,0);
        return val[Findmax(c[x][0])];
    }
    while(val[x]>key&&fa[x]){
        x=fa[x];
    }
    return val[x];
}
int GetNex(int key)
{
    int x=Find(key);
    if(val[x]==key){
        Splay(x,0);
        return val[Findmin(c[x][1])];
    }
    while(val[x]<key&&fa[x]){
        x=fa[x];
    }
    return val[x];
}
int main(){
    int op, x;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&op,&x);
        if(op==1){
            Insert(x);
        }
        else if(op==2){
            Delete(x);
        }
        else if(op==3){
            printf("%d\n",Rank(x));
        }
        else if(op==4){
            printf("%d\n",Kth(x));
        }
        else if(op==5){
            printf("%d\n",GetPre(x));
        }
        else{
            printf("%d\n",GetNex(x));
        }
    }
    return 0;
}
时间: 2024-07-29 20:38:16

【Splay】bzoj3224 Tyvj 1728 普通平衡树的相关文章

BZOJ3224: Tyvj 1728 普通平衡树[treap]

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 9046  Solved: 3840[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小

bzoj3224: Tyvj 1728 普通平衡树(打个splay暖暖手)

(其实今天好热啊? 题目大意:插入,删除,k小,前驱后继,数的排名. splay和treap裸题...过几天补个treap的 splay: #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> using namespace std; const int extar[3]={0,2147483647,-2147483647}; int fa[100010],count[

【权值分块】bzoj3224 Tyvj 1728 普通平衡树

权值分块和权值线段树的思想一致,离散化之后可以代替平衡树的部分功能. 部分操作的时间复杂度: 插入 删除 全局排名 全局K大 前驱 后继 全局最值 O(1) O(1) O(sqrt(n)) O(sqrt(n)) O(sqrt(n)) O(sqrt(n)) O(sqrt(n)) 当然,因为要离散化,所以只能离线. 代码很短,很快,比我的Splay短一倍,快一倍,现在在bzoj上rank6. 1 #include<cstdio> 2 #include<algorithm> 3 #inc

bzoj3224 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) Output 对于操作3,4,

【权值线段树】bzoj3224 Tyvj 1728 普通平衡树

一个板子. #include<cstdio> #include<algorithm> using namespace std; #define N 100001 struct Data { int v,p; }t[N]; bool cmp(const Data &a,const Data &b) { return a.v<b.v; } int T[N<<2],op[N],a[N],n,ma[N],e; void Update(int p,int v

bzoj 3224: Tyvj 1728 普通平衡树.

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 15114  Solved: 6570[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为

3224: Tyvj 1728 普通平衡树(新板子)

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 17048  Solved: 7429[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为

BZOJ 3224: Tyvj 1728 普通平衡树 treap

3224: 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)

3224: Tyvj 1728 普通平衡树

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2566  Solved: 1031[Submit][Status] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)