fhq-treap模板

本文详细介绍了一种基于Treap(随机化二叉查找树)的数据结构实现,通过使用C++模板,实现了包括插入、删除、查找、反转等操作。核心部分展示了如何利用Treap进行权值分裂和排名分裂,以及如何进行节点的合并与分裂,为解决复杂的数据结构问题提供了高效解决方案。

模板保存。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define maxn 500001
using namespace std;
typedef long long ll;
int size[maxn],ch[maxn][2],rnd[maxn],val[maxn],rev[maxn];
int ncnt,x,y,z,rt,n,m;

inline void pushup(int x){
    size[x]=1+size[ch[x][0]]+size[ch[x][1]];
}

inline void pushdown(int rt){
    if(rev[rt]){
        swap(ch[rt][0],ch[rt][1]);
        if(ch[rt][0]) rev[ch[rt][0]]^=1;
        if(ch[rt][1]) rev[ch[rt][1]]^=1;
        rev[rt]=0;
    }

}

inline int new_node(int x){
    size[++ncnt]=1;
    val[ncnt]=x;
    rnd[ncnt]=rand();
    return ncnt;
}
//核心
int merge(int A,int B){
    if(!A||!B) return  A+B;
    if(rnd[A]<rnd[B]){pushdown(A);ch[A][1]=merge(ch[A][1],B);pushup(A);return A;}
    else {pushdown(B);ch[B][0]=merge(A,ch[B][0]);pushup(B);return B;}
}
//权值分裂

void split_1(int now,int k,int &x,int &y){
    if(!now) x=y=0;
    else{
        pushdown(now);
        if(val[now]<=k) x=now,split_1(ch[now][1],k,ch[now][1],y);
        else y=now,split_1(ch[now][0],k,x,ch[now][0]);
        pushup(now);
    }
}

//排名分裂

void split_2(int now,int k,int &x,int &y){
    if(!now) x=y=0;
    else{
        pushdown(now);
        if(k<=size[ch[now][0]]){y=now;split_2(ch[now][0],k,x,ch[now][0]);}
        else{x=now;split_2(ch[now][1],k-size[ch[now][0]]-1,ch[now][1],y);}
        pushup(now);
    }
}

void insert(int &k,int a){
    split_1(k,a,x,y);
    k=merge(merge(x,new_node(a)),y);
}

//会浪费空间,没有回收节点
void del(int &k,int a){
    split_1(k,a,x,z);
    split_1(x,a-1,x,y);
    y=merge(ch[y][0],ch[y][1]);
    k=merge(merge(x,y),z);
}

int rnk(int &k,int a){
    split_1(k,a-1,x,y);
    int res=size[x]+1;
    k=merge(x,y);
    return res;
}

int kth(int now,int k){
    while(1){
        if(k<=size[ch[now][0]]) now=ch[now][0];
        else if(k==size[ch[now][0]]+1) return val[now];
        else k-=size[ch[now][0]]+1,now=ch[now][1];
    }
}

int pred(int &k,int a){
    split_1(k,a-1,x,y);
    int res=kth(x,size[x]);
    k=merge(x,y);
    return res;
}

int succ(int &k,int a){
    split_1(k,a,x,y);
    int res=kth(y,1);
    k=merge(x,y);
    return res;
}

void reverse(int &k,int l,int r){
    split_2(k,l-1,x,y);
    split_2(y,r-l+1,y,z);
    rev[y]^=1;
    k=merge(x,merge(y,z));
}

void print(int &k){
    if(!k) return;
    pushdown(k);
    print(ch[k][0]);
    if(val[k]>=1&&val[k]<=n) printf("%d ",val[k]);
    print(ch[k][1]);
}

int main(){
    srand(time(0));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) insert(rt,i);
    for(int i=1,l,r;i<=m;i++){
        scanf("%d%d",&l,&r);
        reverse(rt,l,r);
    }
    print(rt);
    return 0;
}

 

转载于:https://www.cnblogs.com/elpsycongroo/p/10372199.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值