[模板]splay

[bzoj3224]普通平衡树

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int f[100004],ch[100004][2],key[100004],cnt[100004],size[100004],sz,root;
int n,opt,num;
void clean(int x){//清空
     ch[x][0]=ch[x][1]=f[x]=cnt[x]=key[x]=size[x]=0;
}
int get(int x){//判断当前点是左还是右
    return ch[f[x]][1]==x;//??????
}
void update(int x){//更新size值
     if(x){
        size[x]=cnt[x];
        if(ch[x][0])size[x]+=size[ch[x][0]];
        if(ch[x][1])size[x]+=size[ch[x][1]];
     }
     return;
}
void rotate(int x){
     int old=f[x];
     int oldf=f[old];
     int p=get(x);
     ch[old][p]=ch[x][p^1];
     f[ch[old][p]]=old;
     f[old]=x;
     ch[x][p^1]=old;
     f[x]=oldf;
     if(oldf) ch[oldf][ch[oldf][1]==old]=x;
     update(old);
     update(x);
}
void splay(int x){
     for(int fa;fa=f[x];rotate(x))
         if(f[fa])rotate((get(x)==get(fa)?fa:x));
     root=x;
}
int find(int v){//查询某数的排名
    int ans=0;
    int now=root;
    while(1){
        if(v<key[now]){
            now=ch[now][0];
        }
        else{
            ans+=(ch[now][0]?size[ch[now][0]]:0);
            if(v==key[now]){
                splay(now);
                return ans+1;
            }
            ans+=cnt[now];
            now=ch[now][1];
        }
    }
}
int findx(int x){//查找排名为x的数
    int now=root;
    while(1){
        if(ch[now][0]&&x<=size[ch[now][0]]) now=ch[now][0];
        else{
            int temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];
            if(x<=temp) return key[now];
            x-=temp;
            now=ch[now][1];
        }
    }
}
int pre(){
    int now=ch[root][0];
    while(ch[now][1]) now=ch[now][1];
    return now;
}
int sub(){
    int now=ch[root][1];
    while(ch[now][0]) now=ch[now][0];
    return now;
}
void del(int x){
     int whatever=find(x);
     if(cnt[root]>1){
        cnt[root]--;
        return;
     }
     if(!ch[root][0]&&!ch[root][1]){
        clean(root);
        root=0;
        return;
     }
     if(!ch[root][0]){
        int oldroot=root;
        root=ch[root][1];
        f[root]=0;
        clean(oldroot);
        return;
     }
     else if(!ch[root][1]){
        int oldroot=root;
        root=ch[root][0];
        f[root]=0;
        clean(oldroot);
        return;
     }
     int leftbig=pre();
     int oldroot=root;
     splay(leftbig);
     f[ch[oldroot][1]]=root;
     ch[root][1]=ch[oldroot][1];
     clean(oldroot);
     update(root);
     return;
}
void insert(int v){
     if(!root){
        sz++;
        ch[sz][0]=ch[sz][1]=f[sz]=0;
        key[sz]=v;
        cnt[sz]=1;
        size[sz]=1;
        root=sz;
        return;
     }
     int now=root;
     int fa=0,p;
     while(1){
        if(key[now]==v){
            cnt[now]++;
            update(fa);
            splay(now);
            break;
        }
        fa=now;p=(key[now]<v);
        now=ch[now][p];
        if(now==0){
            sz++;
            ch[sz][0]=ch[sz][1]=0;
            f[sz]=fa;
            key[sz]=v;
            cnt[sz]=1;
            ch[fa][p]=sz;
            update(fa);
            splay(sz);
            break;
        }
     }
     return;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&opt,&num);
        if(opt==1)insert(num);
        if(opt==2)del(num);
        if(opt==3)printf("%d\n",find(num));
        if(opt==4)printf("%d\n",findx(num));
        if(opt==5){
            insert(num);
            printf("%d\n",key[pre()]);
            del(num);
        }
        if(opt==6){
            insert(num);
            printf("%d\n",key[sub()]);
            del(num);
        }
    }
    return 0;
}

splay区间翻转

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#define ll long long
using namespace std;
int m,n,sz,rt,F[100004],s[100004][4],sit[100004],size[100004];
bool tip[100004];
void up(int k){size[k]=size[s[k][0]]+size[s[k][1]]+1;}
void down(int k){
     int l=s[k][0],r=s[k][1];
     if(tip[k]){
        swap(s[k][0],s[k][1]);
        tip[l]^=1;tip[r]^=1;tip[k]=0;
     }
}
void rote(int x,int &k){
     int y=F[x],z=F[y],l,r;
     if(s[y][0]==x)l=0;else l=1;r=l^1;
     if(y==k)k=x;else (s[z][0]==y)?s[z][0]=x:s[z][1]=x;
     F[x]=z;F[y]=x;F[s[x][r]]=y;
     s[y][l]=s[x][r];s[x][r]=y;up(y);up(x);
}
void splay(int x,int &k){
     while(x!=k){
        int y=F[x],z=F[y];
        if(y!=k){
            (s[y][0]==x^s[z][0]==y)?rote(x,k):rote(y,k);
        }
        rote(x,k);
     }
}
void make(int l,int r,int f){
     if(l>r)return;int x=sit[l],be=sit[f];
     if(l==r){
         F[x]=be;size[x]=1;
         (l<f)?s[be][0]=x:s[be][1]=x;return;
     }
     int Mid=(l+r)>>1;x=sit[Mid];
     make(l,Mid-1,Mid);make(Mid+1,r,Mid);
     F[x]=be;up(Mid); (Mid<f)?s[be][0]=x:s[be][1]=x;
}
int search(int k,int rank){
    down(k);int l=s[k][0],r=s[k][1];
    if(size[l]+1==rank)return k;
    else if(size[l]>=rank)return search(l,rank);
    else return search(r,rank-size[l]-1);
}
void rev(int l,int r){
    int x=search(rt,l),y=search(rt,r+2);
    splay(x,rt);splay(y,s[x][1]);
    tip[s[y][0]]^=1;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n+2;i++)sit[i]=++sz;
    make(1,n+2,0);rt=(n+3)>>1;
    for(int i=1;i<=m;i++){int l,r;scanf("%d%d",&l,&r);rev(l,r);}
    for(int i=2;i<=n+1;i++)printf("%d ",search(rt,i)-1);puts("");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值