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[100010],son[100010][3],val[100010],data[100010];
int root,x,y,n,tot;
void read(int &k)
{
    k=0;int f=1;char c=getchar();
    while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar();
    while(c<=‘9‘&&c>=‘0‘)k=k*10+c-‘0‘,c=getchar();
    k*=f;
}
void rotate(int x,int w)
{
    int y=fa[x];
    count[y]=count[y]-count[x]+count[son[x][w]];
    count[x]=count[x]+count[y]-count[son[x][w]];
    son[y][3-w]=son[x][w];
    if(son[x][w])fa[son[x][w]]=y;
    fa[x]=fa[y];
    if(fa[y])if(y==son[fa[y]][1])son[fa[y]][1]=x;
    else son[fa[y]][2]=x;
    fa[y]=x;son[x][w]=y;
}
void splay(int x)
{
    int y;
    while(fa[x])
    {
        y=fa[x];
        if(!fa[y])if(son[y][1]==x)rotate(x,2);else rotate(x,1);
        else
        if(son[fa[y]][1]==y)
        {
            if(son[y][1]==x)rotate(y,2),rotate(x,2);
            else rotate(x,1),rotate(x,2);
        }
        else
        {
            if(son[y][2]==x)rotate(y,1),rotate(x,1);
            else rotate(x,2),rotate(x,1);
        }
    }
    root=x;
}
int search(int x,int w)
{
    while(data[x]!=w)
    {
        if(data[x]==w)return x;
        if(data[x]>w)
        {
            if(!son[x][1])break;
            x=son[x][1];
        }
        else
        {
            if(!son[x][2])break;
            x=son[x][2];
        }
    }
    return x;
}
void insert(int w)
{
    if(!tot)
    {
        tot=count[1]=val[1]=root=1;data[1]=w;fa[1]=0;
        return;
    }
    int k=search(root,w),kk=0;
    if(data[k]==w)val[k]++,kk=k;
    else
    {
        data[++tot]=w;count[tot]=val[tot]=1;fa[tot]=k;
        if(w<data[k])son[k][1]=tot;else son[k][2]=tot;
    }
    while(k)count[k]++,k=fa[k];
    if(kk)splay(kk);else splay(tot);
}
int ext(int x,int w)
{
    int k=search(x,extar[w]);
    splay(k);
    return data[k];
}
void del(int w)
{
    int k=search(root,w);
    splay(k);
    if(data[k]==w)
    {
        if(val[k]>1)val[k]--,count[k]--;
        else
        if(!son[k][1])
        {
            root=son[k][2];
            fa[root]=fa[k]=son[k][2]=count[k]=val[k]=data[k]=0;
        }
        else
        {
            fa[son[k][1]]=0;ext(son[k][1],1);
            son[root][2]=son[k][2];
            if(son[k][2])fa[son[k][2]]=root;
            count[root]+=count[son[k][2]];
            fa[k]=son[k][1]=son[k][2]=data[k]=val[k]=count[k]=0;
        }
    }
}
int pred(int w)
{
    int k=search(root,w);
    splay(k);
    if(data[k]<w)return data[k];
    return ext(son[k][1],1);
}
int succ(int x)
{
    int k=search(root,x);
    splay(k);
    if(data[k]>x)return data[k];
    return ext(son[k][2],2);
}
int kth(int cnt,int w)
{
    int i=root;
    while((i!=0)&&(count[son[i][w]]>=cnt||count[son[i][w]]+val[i]<cnt))
    {
        if(count[son[i][w]]+val[i]<cnt)
        {
            cnt-=count[son[i][w]]+val[i];
            i=son[i][3-w];
        }
        else i=son[i][w];
    }
    splay(i);
    return data[i];
}
int findnum(int x,int w)
{
    int k=search(root,x);
    splay(k);
    return count[son[k][w]]+1;
}
int main()
{
    read(n);
    for(int i=1;i<=n;i++)
    {
        read(x);read(y);
        switch(x)
        {
            case 1:insert(y);break;
            case 2:del(y);break;
            case 3:printf("%d\n",findnum(y,1));break;
            case 4:printf("%d\n",kth(y,1));break;
            case 5:printf("%d\n",pred(y));break;
            case 6:printf("%d\n",succ(y));break;
            default:break;
        }
    }
}

时间: 2024-12-20 09:30:22

bzoj3224: Tyvj 1728 普通平衡树(打个splay暖暖手)的相关文章

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的前驱(前驱定义为小

【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

【权值分块】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,且最大的数)