各种平衡树板子

平衡树:

Splay

#include <bits/stdc++.h>
#define root T[0].son[1]
using namespace std;
int read() {
    int re = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {if (ch == '-') f = -f; ch = getchar();}
    while ('0' <= ch && ch <= '9') {re = re * 10  + ch - '0'; ch = getchar();}
    return re * f;
}
const int N = 1e5 + 3;
const int INF = 1e7 + 3;
int n, cnt;
struct node{
    int v,recy,sum;//权值 重复个数 子树总个数 
    int fa,son[2];//爹 儿子
}T[N];
void pushup(int x){//更新大小 
    T[x].sum=T[T[x].son[0]].sum+T[T[x].son[1]].sum+T[x].recy;
}
bool identify(int x){//确定父子关系 
    return T[T[x].fa].son[0]==x?0:1;
}
void connect(int x,int fa,int son){//认亲 
    T[x].fa=fa;
    T[fa].son[son]=x;
}
void rotate(int x){//旋转 
    int y=T[x].fa;
    int z=T[y].fa;
    int zson=identify(y);
    int yson=identify(x);
    int xson=T[x].son[yson^1];
    connect(xson,y,yson);
    connect(y,x,yson^1);
    connect(x,z,zson);
    pushup(y);
    pushup(x);
    return ;
}
void splay(int x,int to){//移动x到to的位置 
    int tofa=T[to].fa;
    while(tofa!=T[x].fa){
        int fa=T[x].fa;
        int gfa=T[fa].fa;
        if(gfa!=tofa){
            if(identify(x)!=identify(fa)){
                rotate(x);
            }else{
                rotate(fa);
            }
        }
        rotate(x);
    }
    if(to==root){
        root=x;
    }
}
int newpoint(int v,int fa){//建新点 
    T[++cnt].fa=fa;
    T[cnt].v=v;
    T[cnt].sum=T[cnt].recy=1;
    return cnt;
}
void Insert(int v){//插入权值为v的点 
    int now=root;
    if(!root){root=newpoint(v,0);}
    else{
        while(1){
            T[now].sum++;
            if(T[now].v==v){
                T[now].recy++;
                splay(now,root);
                return;
            }
            int next=T[now].v<v?1:0;
            if(!T[now].son[next]){
                T[now].son[next]=newpoint(v,now);
                splay(cnt,root);
                return;
            }
            now=T[now].son[next];
        }
    }
}
int find(int v){//查询权值为v的点在的位置 
    int now=root;
    while(1){
        if(T[now].v==v){
            splay(now,root);
            return now;
        }
        int next=T[now].v<v?1:0;
        if(!T[now].son[next]){
            return 0;
        }
        now=T[now].son[next];
    }
}
void delet(int v){//删除权值为v的点 
    int now=find(v);
    if(!now)return;
    if(T[now].recy>1){
        T[now].recy--;
        T[now].sum--;
    }else{
        if(!T[now].son[0]&&!T[now].son[1]){
            root=0;
        }else if(!T[now].son[0]){
            root=T[now].son[1];
            T[root].fa=0;
        }else{
            int lef=T[now].son[0];
            while(T[lef].son[1]){
                lef=T[lef].son[1];
            }
            splay(lef,T[now].son[0]);
            connect(T[now].son[1],lef,1);
            connect(lef,0,1);
            pushup(lef);
        }
    }
}
int _rank(int v){//查询权值为v的点的排名 
    return T[T[find(v)].son[0]].sum+1;
}
int _kth(int k){//查询第x名的权值 
    int now=root;
    while(1){
        int used=T[now].sum-T[T[now].son[1]].sum;
        if(T[T[now].son[0]].sum<k&&k<=used){
            splay(now,root);
            return T[now].v;
        }
        if(k<used){
            now=T[now].son[0];
        } 
        else{
            k-=used;
            now=T[now].son[1];
        }
    }
}
int lower(int x){//前驱 
    int now=root,val=-0x3f3f3f3f;
    while(now){
        if(T[now].v<x){
            val=max(val,T[now].v);
        }
        if(T[now].v<x){
            now=T[now].son[1];
        }else {
            now=T[now].son[0];   
        } 
    }
    return val;
}
int upper(int x){//后继 
    int now=root,val=0x3f3f3f3f;
    while(now){
        if(T[now].v>x){
            val=min(val,T[now].v);
        }
        if(T[now].v<=x){
            now=T[now].son[1];
        }else{
            now=T[now].son[0]; 
        }    
    }
    return val;
}
int main () {
    n = read();
    while (n--) {
        int opt = read();
        int x = read();
        if (opt == 1) Insert(x);
        else if (opt == 2) delet(x);
        else if (opt == 3) printf("%d\n", _rank(x));
        else if (opt == 4) printf("%d\n", _kth(x));
        else if (opt == 5) printf("%d\n", lower(x));
        else if (opt == 6) printf("%d\n", upper(x));
    }
    return 0;
}
Splay

Treap

#include<bits/stdc++.h>
using namespace std;
const int N=300010;
int n,cnt,root;
struct node{
    int v,recy,sum;//权值 重复个数 子树总个数 
    int son[2];// 儿子
    int rk;//随机值 
}T[N];
void pushup(int x){//更新大小 
    T[x].sum=T[T[x].son[0]].sum+T[T[x].son[1]].sum+T[x].recy;
}
void rotate(int &x,int next){//旋转 
    int y=T[x].son[next^1];
    T[x].son[next^1]=T[y].son[next];
    T[y].son[next]=x;
    pushup(x);
    pushup(y);
    x=y;
}
int newpoint(int v){//建新点 
    T[++cnt].v=v;
    T[cnt].sum=T[cnt].recy=1;
    T[cnt].rk=rand();
    return cnt;
}
void Insert(int &x,int v){//插入权值为v的点
    if(!x){x=newpoint(v);return;}
    if(T[x].v==v){
        T[x].recy++;
        T[x].sum++;
        return;
    }
    int next=T[x].v<v?1:0;
    Insert(T[x].son[next],v);
    if(T[x].rk<T[T[x].son[next]].rk){
        rotate(x,next^1);
    }
    pushup(x);
}
void delet(int &x,int v){//删除权值为v的点 
    if(!x)return;
    if(v<T[x].v){
        delet(T[x].son[0],v);
    }
    else if(v>T[x].v){
        delet(T[x].son[1],v);
    }
    else {
        if(!T[x].son[0]&&!T[x].son[1]){
            T[x].recy--;
            T[x].sum--;
            if(!T[x].recy){
                x=0;
            }
        }else if(T[x].son[0]&&T[x].son[1]){
            int next=T[T[x].son[0]].rk>T[T[x].son[1]].rk?1:0;
            rotate(x,next);
            delet(T[x].son[next],v);
        }else{
            int next=!T[x].son[1];
            rotate(x,next);
            delet(T[x].son[next],v);
        }
    }
    pushup(x);
}
int _rank(int x,int v){//查询权值为v的点的排名 
    if(!x){
        return 0;
    }
    else if(T[x].v<v){
        return T[T[x].son[0]].sum+T[x].recy+_rank(T[x].son[1],v);
    }else if(T[x].v>v){
        return _rank(T[x].son[0],v);
    }else{
        return T[T[x].son[0]].sum+1;
    }             
}
int _kth(int x,int k){//查询第k名的权值 
    if(!x){
        return 0;
    }else if(T[T[x].son[0]].sum>=k){
        return _kth(T[x].son[0],k);
    }else if(T[T[x].son[0]].sum+T[x].recy<k){
        return _kth(T[x].son[1],k-T[T[x].son[0]].sum-T[x].recy);
    }
    else return T[x].v;
}
int lower(int x,int v){//前驱 
    if(!x){
        return -0x3f3f3f3f;
    }
    if(T[x].v>=v){
        return lower(T[x].son[0],v);
    }else{
        return max(T[x].v,lower(T[x].son[1],v));
    }
}
int upper(int x,int v){//后继 
    if(!x){
        return 0x3f3f3f3f;
    }
    if(T[x].v<=v){
        return upper(T[x].son[1],v);
    }else {
        return min(T[x].v,upper(T[x].son[0],v));
    }
}
int main(){
    scanf("%d",&n);
    for (int i=0;i<n;++i)
    {
        int opt,x;
        scanf("%d%d",&opt,&x);
        if (opt==1) Insert(root,x);
        else if (opt==2) delet(root,x);
        else if (opt==3) printf("%d\n",_rank(root,x));
        else if (opt==4) printf("%d\n",_kth(root,x));
        else if (opt==5) printf("%d\n",lower(root,x));
        else if (opt==6) printf("%d\n",upper(root,x));
    }
    return 0;
}
Treap

fhq

#include<bits/stdc++.h>
using namespace std;
const int N=400010;
int cnt,x,y,z,root;
int n,m;
struct node{
    int v,sum;//权值 子树总个数 
    int son[2];//儿子
    int rk;//随机值 
}T[N];
inline int read(){
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
void pushup(int x){//更新大小 
    T[x].sum=T[T[x].son[0]].sum+T[T[x].son[1]].sum+1;
}
int newpoint(int v){//建新点 
    T[++cnt].v=v;
    T[cnt].sum=1;
    T[cnt].rk=rand();
    return cnt;
}
int merge(int x,int y){//合并 
    if(!x||!y) return  x+y;
    if(T[x].rk<T[y].rk){
        T[x].son[1]=merge(T[x].son[1],y); 
        pushup(x); 
        return x;
    }else{
        T[y].son[0]=merge(x,T[y].son[0]); 
        pushup(y); 
        return y;     
    }
}

void split(int now,int k,int &x,int &y){//分裂(权值) 
    if(!now) x=y=0;
    else {
        if(T[now].v<=k){
            x=now;
            split(T[now].son[1],k,T[now].son[1],y);
        }else{
            y=now;
            split(T[now].son[0],k,x,T[now].son[0]);
        }
        pushup(now);
    }
}
void _split(int now,int k,int &x,int &y){//分裂(排名) 
    if(!now) x=y=0;
    else {
        if(T[T[now].son[0]].sum<k){
            x=now;
            split(T[now].son[1],k-T[T[now].son[0]].sum-1,T[now].son[1],y);
        }else{
            y=now;
            split(T[now].son[0],k,x,T[now].son[0]);
        }
        pushup(now);
    }
}
void Insert(int v){//输入 
    split(root,v,x,y);
    root=merge(merge(x,newpoint(v)),y);
}
void delet(int v){//删除 
    split(root,v,x,z);
    split(x,v-1,x,y);
    y=merge(T[y].son[0],T[y].son[1]);
    root=merge(merge(x,y),z);
}
int _rank(int v){//权值为v点的排名 
    split(root,v-1,x,y);
    int ans=T[x].sum+1;
    root=merge(x,y);
    return ans;
}
int find(int now,int k){//查询第k大点的编号 
    while(1){
        if(k<=T[T[now].son[0]].sum){
            now=T[now].son[0];
        }else if(k==T[T[now].son[0]].sum+1){
            return now;
        }else{
            k-=T[T[now].son[0]].sum+1;
            now=T[now].son[1];
        }
    }
}
int _kth(int k){//查询第k大点的权值 
    return T[find(root,k)].v;
}
int lower(int v){//前驱 
    split(root,v-1,x,y);
    int ans=T[find(x,T[x].sum)].v;
    root=merge(x,y);
    return ans;
}
int upper(int v){//后继 
    split(root,v,x,y);
    int ans=T[find(y,1)].v;
    root=merge(x,y);
    return ans;
}
int main(){
    scanf("%d",&n);
    for (int i=0;i<n;++i){
        int opt,x;
        scanf("%d%d",&opt,&x);
        if (opt==1) Insert(x);
        else if (opt==2) delet(x);
        else if (opt==3) printf("%d\n",_rank(x));
        else if (opt==4) printf("%d\n",_kth(x));
        else if (opt==5) printf("%d\n",lower(x));
        else if (opt==6) printf("%d\n",upper(x));
    }
    return 0;
}
fhq

替罪羊(调了一天半呢....网上为什么都用的指针版的  自己写了个不用指针的)

#include<bits/stdc++.h>
#define L(x) e[(x)].son[0]
#define R(x) e[(x)].son[1]
using namespace std;
const int N=400010;
struct node{
    int son[2], val, imag, real;
    bool v;
}e[N];
int avai[N]; 
int used[N];
int root, A, B, cnt, aim,bad,badfa;
int newpoint(int v){
    e[++cnt].val = v;
    e[cnt].v=1;
    e[cnt].imag=e[cnt].real = 1;
    e[cnt].son[0] = e[cnt].son[1] = 0;
    return cnt;
}
bool check(int x){
    if((double)max(e[L(x)].imag,e[R(x)].imag)*1.0>(double)e[x].imag*0.8)return 0;
    else return 1;
}
void pushup(int x){
    e[x].imag=e[L(x)].imag+e[R(x)].imag+1;
    e[x].real=e[L(x)].real+e[R(x)].real+e[x].v;
}
void pia(int x) {
    if(L(x))pia(L(x));
    if(e[x].v)used[++A] = x;
    if(R(x))pia(R(x));
}
int build(int l, int r){
    if(l>r)return 0;
    int mid = (l+r)>>1;
    int x = used[mid];
    L(x)=build(l,mid-1);
    R(x)=build(mid+1,r);
    pushup(x);
    return x;
}
void rebuild(){
    if(!bad)return;
    int next=(R(badfa)==bad?1:0),last=bad;
    A=0;pia(bad);bad=build(1,A);
    e[badfa].son[next]=bad;
    if(last==root)root=bad;
    return;
}
int Ins(int x, int v,int fa){
    if(!x){
        x=newpoint(v);
        return x;
    }
    e[x].imag++;
    e[x].real++;
    if(e[x].val >= v) L(x)=Ins(L(x), v,x); 
    else R(x)=Ins(R(x), v,x);
    if(!check(x)&&!bad){
        bad=x;
        badfa=fa;
    }
    return x;
}
void Insert(int v){
    bad=badfa=0;
    root=Ins(root,v,0);
    rebuild();
}
int _rank(int k){
    int x = root;
    int ans = 1;
    while(x){
        if(e[x].val >= k) x = L(x);
        else{
            ans += e[L(x)].real + e[x].v;
            x = R(x);
        }
    }
    return ans;
}
int _kth(int k){
    int x = root;
    while(x){
        if(e[x].v&&e[L(x)].real+1 == k) return e[x].val;
        else if(e[L(x)].real >= k) x = L(x);
        else{
            k -= e[L(x)].real + e[x].v;
            x = R(x);
        }
    }
    return 0;
}
void delet_pos(int x, int v){
    if(e[x].v&&e[L(x)].real+ 1 == v) {
        e[x].v = 0; 
        e[x].real--; 
        return;
    }
    e[x].real--;
    if(e[L(x)].real + e[x].v >= v) delet_pos(L(x), v);
    else delet_pos(R(x),v-e[L(x)].real-e[x].v);
}
void delet(int v){
    delet_pos(root, _rank(v));
}
int lower(int v){
    return _kth(_rank(v)-1);
}
int upper(int v){
    return _kth(_rank(v+1));
}
int main()
{
    int opt, x, m;
    scanf("%d",&m);
    while(m--)
    {
        scanf("%d%d",&opt,&x);
        if(opt == 1){Insert(x);}
        if(opt == 2){delet(x);}
        if(opt == 3){printf("%d\n",_rank(x));}
        if(opt == 4){printf("%d\n",_kth(x));}
        if(opt == 5){printf("%d\n",lower(x));}
        if(opt == 6){printf("%d\n",upper(x));}
    }
    return 0;
}
scapegoat tree

 

可持久化平衡树:

fhq

#include<bits/stdc++.h>
using namespace std;
const int N=500010;
int cnt,x,y,z,root[N],tot;
int n,m;
struct node{
    int v,sum;//权值 子树总个数 
    int son[2];//儿子
    int rk;//随机值 
}T[N*50];
inline int read(){
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
void pushup(int x){//更新大小 
    if(x)T[x].sum=T[T[x].son[0]].sum+T[T[x].son[1]].sum+1;
}
int newpoint(int v){//建新点 
    T[++cnt].v=v;
    T[cnt].sum=1;
    T[cnt].rk=rand();
    return cnt;
}
int copy(int x){
    T[++cnt]=T[x];
    return cnt;
}
void split(int now,int k,int &x,int &y){//分裂(权值)
    if(!now) x=y=0;
    else {
//    pushdown(now); 
        if(T[now].v<=k){
            x=copy(now);
            split(T[x].son[1],k,T[x].son[1],y);
        }else{
            y=copy(now);
            split(T[y].son[0],k,x,T[y].son[0]);
        }
        pushup(x);
        pushup(y);
    }
}
void _split(int now,int k,int &x,int &y){//分裂(排名)
    if(!now) x=y=0;
    else {
//    pushdown(now); 
        if(T[T[now].son[0]].sum<k){
            x=copy(now);
            split(T[x].son[1],k-T[T[now].son[0]].sum-1,T[x].son[1],y);
        }else{
            y=copy(now);
            split(T[y].son[0],k,x,T[y].son[0]);
        }
        pushup(x);
        pushup(y);
    }
}
int merge(int x,int y){//合并 
    if(!x||!y) return  x+y;
//    pushdown(x);
//    pushdown(y); 
    if(T[x].rk<T[y].rk){
        int nu=copy(x);
        T[nu].son[1]=merge(T[nu].son[1],y); 
        pushup(nu);
        return nu;
    }else{
        int nu=copy(y);
        T[nu].son[0]=merge(x,T[nu].son[0]); 
        pushup(nu);
        return nu;    
    }
}
//另外 在需要推标记的题中如果pushdown会改变树的形态 注意开新点
/*  即在pushdown函数中加入以下代码 
    if(T[x].son[0])T[x].son[0]=copy(T[x].son[0]);
    if(T[x].son[1])T[x].son[1]=copy(T[x].son[1]);
*/
// 因为新的版本继承的旧版本的点嘛 pushdown的时候不能牵连到旧版本嘛 
void Insert(int ed,int v){//输入 
    x=y=z=0;
    split(root[ed],v,x,y);
    root[ed]=merge(merge(x,newpoint(v)),y);
}
void delet(int ed,int v){//删除 
    x=y=z=0;
    split(root[ed],v,x,z);
    split(x,v-1,x,y);
    y=merge(T[y].son[0],T[y].son[1]);
    root[ed]=merge(merge(x,y),z);
}
int _rank(int ed,int v){//权值为v点的排名 
    x=y=z=0;
    split(root[ed],v-1,x,y);
    int ans=T[x].sum+1;
    root[ed]=merge(x,y);
    return ans;
}
int find(int now,int k){//查询第k大点的编号 
    while(1){
        if(k<=T[T[now].son[0]].sum){
            now=T[now].son[0];
        }else if(k==T[T[now].son[0]].sum+1){
            return now;
        }else{
            k-=T[T[now].son[0]].sum+1;
            now=T[now].son[1];
        }
    }
}
int _kth(int ed,int k){//查询第k大点的权值 
    x=y=z=0;
    return T[find(root[ed],k)].v;
}
int lower(int ed,int v){//前驱 
    x=y=z=0;
    split(root[ed],v-1,x,y);
    if(!x)return -2147483647;
    int ans=T[find(x,T[x].sum)].v;
    root[ed]=merge(x,y);
    return ans;
}
int upper(int ed,int v){//后继 
    x=y=z=0;
    split(root[ed],v,x,y);
    if(!y)return 2147483647;
    int ans=T[find(y,1)].v;
    root[ed]=merge(x,y);
    return ans;
}
int main(){
    srand(time(NULL));
    scanf("%d",&n);
    for (int i=1;i<=n;++i){//注意:由于模板题题意这里必须写成i=1 
        int opt,x,E;      
        scanf("%d%d%d",&E,&opt,&x);
        root[i]=root[E];
        if (opt==1) Insert(i,x);
        else if (opt==2) delet(i,x);
        else if (opt==3) printf("%d\n",_rank(i,x));
        else if (opt==4) printf("%d\n",_kth(i,x));
        else if (opt==5) printf("%d\n",lower(i,x));
        else if (opt==6) printf("%d\n",upper(i,x));
    }
    return 0;
}
fhq

其他待补....

posted @ 2020-01-20 23:52  passione  阅读(178)  评论(0编辑  收藏  举报