Treap模板(bzoj 3224)

bzoj 3224 普通平衡树

数据结构支持六种操作

#include<bits/stdc++.h>
using namespace std;


typedef long long ll;

const int maxn=1e5+7;

struct Tree{
    int l,r;
    int val,dat;
    int cnt,size1;
}a[maxn];

int tot,root,inf=0x7fffffff;

int New(int val){
    a[++tot].val=val;
    a[tot].dat=rand();
    a[tot].cnt=a[tot].size1=1;
    return tot;
}

void updata(int p){
    a[p].size1=a[a[p].l].size1+a[a[p].r].size1+a[p].cnt;
}

void build(){
    New(-inf),New(inf);
    root=1;
    a[root].r=2;
}

void zig(int& p){
    int q=a[p].l;
    a[p].l=a[q].r;
    a[q].r=p;
    p=q;
    updata(a[p].r);
    updata(p);
}

void zag(int& p){
    int q=a[p].r;
    a[p].r=a[q].l;
    a[q].l=p;
    p=q;
    updata(a[p].l);
    updata(p);
}

void Insert(int& p,int val){
    if(p==0){
        p=New(val);
        return ;
    }
    if(val==a[p].val){
        ++a[p].cnt;
        updata(p);
        return ;
    }
    if(val<a[p].val){
        Insert(a[p].l,val);
        if(a[p].dat<a[a[p].l].dat) zig(p);
    }
    else{
        Insert(a[p].r,val);
        if(a[p].dat<a[a[p].r].dat) zag(p);
    }
    updata(p);
}

void Remove(int& p,int val){
    if(p==0) return ;
    if(val==a[p].val){
        if(a[p].cnt>1){
            --a[p].cnt;
            updata(p);
            return ;
        }
        if(a[p].l||a[p].r){
            if(a[p].r==0||a[a[p].l].dat>a[a[p].r].dat){
                zig(p);
                Remove(a[p].r,val);
            }
            else{
                zag(p);
                Remove(a[p].l,val);
            }
            updata(p);
        }
        else p=0;
        return ;

    }
    val<a[p].val?Remove(a[p].l,val):Remove(a[p].r,val);
    updata(p);
}

int getrank(int p,int val){
    if(p==0) return 0;
    if(val==a[p].val) return a[a[p].l].size1+1;
    if(val<a[p].val) return getrank(a[p].l,val);
    return getrank(a[p].r,val)+a[a[p].l].size1+a[p].cnt;
}

int getval(int p,int rank1){
    if(p==0) return inf;
    if(a[a[p].l].size1>=rank1) return getval(a[p].l,rank1);
    if(a[a[p].l].size1+a[p].cnt>=rank1) return a[p].val;
    return getval(a[p].r,rank1-a[a[p].l].size1-a[p].cnt);
}

int getpre(int val){
    int p=root;
    int ans=1;
    while(p){
        if(val==a[p].val){
            if(a[p].l){
                p=a[p].l;
                while(a[p].r) p=a[p].r;
                ans=p;
            }
            break;
        }
        if(val>a[p].val&&a[p].val>a[ans].val) ans=p;
        p=(val>a[p].val?a[p].r:a[p].l);
    }
    return a[ans].val;
}

int getnext(int val){
    int p=root;
    int ans=2;
    while(p){
        if(val==a[p].val){
            if(a[p].r){
                p=a[p].r;
                while(a[p].l) p=a[p].l;
                ans=p;
            }
            break;
        }
        if(val<a[p].val&&a[p].val<a[ans].val) ans=p;
        p=(val>a[p].val?a[p].r:a[p].l);
    }
    return a[ans].val;
}

int main(){
    build();
    int n;
    scanf("%d",&n);
    int id,x;
    while(n--){
        scanf("%d%d",&id,&x);
        if(id==1){
            Insert(root,x);
        }
        else if(id==2){
            Remove(root,x);
        }
        else if(id==3){
            printf("%d\n",getrank(root,x)-1);//负无穷占了一位;
        }
        else if(id==4){
            printf("%d\n",getval(root,x+1));//负无穷占了最小位置;
        }
        else if(id==5){
            printf("%d\n",getpre(x));
        }
        else{
            printf("%d\n",getnext(x));
        }

    }
    return 0;
}

 

权值线段树写法

#include<bits/stdc++.h>
using namespace std;
 
typedef long long ll;
const int inf=0x3f3f3f3f;
 
const int maxn=1e5+7;
int a[maxn];
int m;
int sum[maxn<<2|1];
void quchong(int n){
    sort(a+1,a+1+n);
    m=unique(a+1,1+a+n)-a-1;
}
 
int getid(int x){
    return lower_bound(a+1,a+1+m,x)-a;
}
 
void build(int l,int r,int k){
    memset(sum,0,sizeof(sum));
}
 
void updata(int l,int r,int k,int id,int val){
    if(l==r){
        sum[k]+=val;
        return ;
    }
    int mid=(l+r)>>1;
    if(id<=mid) updata(l,mid,k<<1,id,val);
    else updata(mid+1,r,k<<1|1,id,val);
    sum[k]=sum[k<<1]+sum[k<<1|1];
}
 
//查询排名为x的数
int myfind_x(int l,int r,int k,int x){
    if(l==r) return l;
    int mid=(l+r)>>1;
    if(sum[k<<1]>=x) return myfind_x(l,mid,k<<1,x);
    return myfind_x(mid+1,r,k<<1|1,x-sum[k<<1]);
}
 
//[L,R] 区间内的所有数的次数和;
int myfind_h(int L,int R,int l,int r,int k){
    if(L>R) return 0;
    if(l>=L&&r<=R) return sum[k];
    int mid=(l+r)>>1;
    int res=0;
    if(L<=mid) res+=myfind_h(L,R,l,mid,k<<1);
    if(R>mid) res+=myfind_h(L,R,mid+1,r,k<<1|1);
    return res;
}
 
struct Node{
    int id;
    int x;
}b[maxn];
 
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%d%d",&b[i].id,&b[i].x);
        a[i]=b[i].x;
    }
    quchong(n);
    for(int i=1;i<=n;++i){
        if(b[i].id==1) updata(1,m,1,getid(b[i].x),1);
        else if(b[i].id==2) updata(1,m,1,getid(b[i].x),-1);
        else if(b[i].id==3) printf("%d\n",myfind_h(1,getid(b[i].x)-1,1,m,1)+1);
        else if(b[i].id==4) printf("%d\n",a[myfind_x(1,m,1,b[i].x)]);
        else if(b[i].id==5) printf("%d\n",a[myfind_x(1,m,1,myfind_h(1,getid(b[i].x)-1,1,m,1))]);
        else printf("%d\n",a[myfind_x(1,m,1,myfind_h(1,getid(b[i].x),1,m,1)+1)]);
    }
 
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值