感觉范浩强真的巨

博主只刷了模板所以就讲基础

fhq-treap

又形象的称为非旋转treap

顾名思义

保留了treap的随机数堆的特点,并以此作为复杂度正确的条件

并且所有的实现不用旋转!

思路自然,结构直观,代码简洁,理解轻松。

虽然不能支持LCT(起码我不会)

但是相较于splay可以可持久化(splay理论上旋转会造成空间爆炸)

基本和splay平分秋色,甚至更胜一筹

 

核心操作只有两个:

merge:把两个树合成一个树

int merge(int x,int y){
    if(!x||!y) return x+y;
    if(t[x].pri<t[y].pri){
        t[x].ch[1]=merge(t[x].ch[1],y);
        pushup(x);
        return x;
    }else{
        t[y].ch[0]=merge(x,t[y].ch[0]);
        pushup(y);
        return y;
    }
}

(merge最后只有一棵树,所以可以带返回值)

需要注意的是,merge的两棵树,默认x的所有权值都小于y!

split:把一个树分裂成两个树

按照权值k分裂

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

按照sz分裂:(维护序列时候)

void split(int now,int k,int &x,int &y){
    if(!now) {
        x=0;y=0;return;
    }
    pushdown(now);
    if(t[t[now].ch[0]].sz+1<=k){
        k-=t[t[now].ch[0]].sz+1;
        x=now;
        split(t[now].ch[1],k,t[now].ch[1],y);
    }else{
        y=now;
        split(t[now].ch[0],k,x,t[now].ch[0]);
    }
    pushup(now);
}

 

(由于split最后得到两棵树,所以只能用&)

模拟一下很直观的。

 

 

【模板】普通平衡树

其他的操作直接看代码就可以理解:

fhq不用记录father的

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
    char ch;x=0;bool fl=false;
    while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
namespace Miracle{
const int N=100000+5;
const int inf=0x3f3f3f3f;
struct node{
    int pri;
    int ch[2];
    int val;
    int sz;
}t[N];
int tot;
int rt;
int n;
int nc(int v){
    t[++tot].val=v;t[tot].sz=1;
    t[tot].pri=rand();
    return tot;
}
void pushup(int x){
    t[x].sz=t[t[x].ch[1]].sz+t[t[x].ch[0]].sz+1;
}
int merge(int x,int y){
    if(!x||!y) return x+y;
    if(t[x].pri<t[y].pri){
        t[x].ch[1]=merge(t[x].ch[1],y);
        pushup(x);
        return x;
    }else{
        t[y].ch[0]=merge(x,t[y].ch[0]);
        pushup(y);
        return y;
    }
}
void split(int now,int k,int &x,int &y){
    if(!now){
        x=0;y=0;return;
    }
    if(t[now].val<=k){
        x=now;
        split(t[now].ch[1],k,t[now].ch[1],y);
    }else{
        y=now;
        split(t[now].ch[0],k,x,t[now].ch[0]);
    }
    pushup(now);
}
int kth(int now,int k){
    int x=now;
    while(1){
        if(t[t[x].ch[0]].sz+1==k) return x;
        int tmp=t[t[x].ch[0]].sz+1;
        if(tmp<k){
            k-=tmp;x=t[x].ch[1];
        }else{
            x=t[x].ch[0];
        }
    }
}
int main(){
    srand(19260817);
    rd(n);
    int op,x;
    int le=0,ri=0;
    while(n--){
        rd(op);rd(x);
        switch (op){
            case 1:{
                split(rt,x,le,ri);
                rt=merge(merge(le,nc(x)),ri);
                break;
            }
            case 2:{
                int zz;
                split(rt,x,le,zz);
                split(le,x-1,le,ri);
                //le=t[le].ch[0];//warning!!! maybe wrong
                ri=merge(t[ri].ch[0],t[ri].ch[1]);
                rt=merge(merge(le,ri),zz);
                break;
            }
            case 3:{
                split(rt,x-1,le,ri);
                printf("%d\n",t[le].sz+1);
                rt=merge(le,ri);
                break;
            }
            case 4:{
                int tmp=kth(rt,x);
                printf("%d\n",t[tmp].val);
                break;
            }
            case 5:{
                split(rt,x-1,le,ri);
                int tmp=kth(le,t[le].sz);
                printf("%d\n",t[tmp].val);
                rt=merge(le,ri);
                break;
            }
            case 6:{
                split(rt,x,le,ri);
                int tmp=kth(ri,1);
                printf("%d\n",t[tmp].val);
                rt=merge(le,ri);
                break;
            }
        }
    }
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2019/1/5 21:36:18
*/
View Code

相关文章: