「学习笔记」bzoj 3224 & bzoj 3223 平衡树两件套 - 非旋treap - 学习笔记

非选treap真是个好东西!
bzoj3224有个实现细节我看网上都是错的,即split的时候,可能有重复元素(也就是1 x了相同的x很多次),然后求kth的时候不能把那个点拆成两个(否则merge的时候正确性和代码复杂度和时间复杂度都不能保证……吧?)。还有就是非旋treap其实不需要像splay一样一开始插入一个inf和INF来减少特判。
bzoj 3224:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#define ull unsigned long long
#define gc getchar()
#define mp make_pair
#define fir first
#define sec second
#define N 100010
using namespace std;
typedef pair<int,int> pii;
inline int inn()
{
    int x=0,s=1,ch;while(((ch=gc)<'0'||ch>'9')&&ch!='-');
    if(ch^'-') x=ch^'0';else s=-1;
    while((ch=gc)>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');
    return s*x;
}
int ch[N][2],sz[N],cnt[N],val[N];ull key[N];
struct Rand{
    ull x;Rand() { x=0; }
    inline ull operator()() { return x*=998244353,x^=1000000007,x^=(x<<13)^(x>>5)^945632; }
}rnd;
struct Treap{
    int rt,node_cnt;
    Treap() { rt=node_cnt=0,insert(INT_MIN+10),insert(INT_MAX-10),cnt[1]=cnt[2]=sz[1]=sz[2]=0; }
    inline int push_up(int x) { return sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x]; }
    inline int setc(int x,int y,int z) { return ch[x][z]=y,push_up(x); }
    inline int new_node(int v,int x=0) { return x=++node_cnt,val[x]=v,key[x]=rnd(),cnt[x]=sz[x]=1,x; }
    int merge(int x,int y)
    {
        if(!x||!y) return x+y;
        if(key[x]<key[y]) return setc(x,merge(ch[x][1],y),1),x;
        else return setc(y,merge(x,ch[y][0]),0),y;return 0;
    }
    pii splitk(int x,int k)
    {
        if(!x||!k) return mp(0,x);pii t;
        if(k<=sz[ch[x][0]])
            return t=splitk(ch[x][0],k),setc(x,t.sec,0),mp(t.fir,x);
        else return k-=sz[ch[x][0]]+cnt[x],k=max(k,0),
            t=splitk(ch[x][1],k),setc(x,t.fir,1),mp(x,t.sec);
        return mp(0,0);
    }
    pii splitv(int x,int v)
    {
        if(!x) return mp(0,0);pii t;
        if(val[x]<=v) return t=splitv(ch[x][1],v),setc(x,t.fir,1),mp(x,t.sec);
        else return t=splitv(ch[x][0],v),setc(x,t.sec,0),mp(t.fir,x);
        return mp(0,0);
    }
    inline int insert(int v)
    {
        pii a=splitv(rt,v),b=splitv(a.fir,v-1);
        if(b.sec) cnt[b.sec]++,sz[b.sec]++;
        else b.sec=new_node(v);
        return rt=merge(merge(b.fir,b.sec),a.sec);
    }
    inline int del(int v)
    {
        pii a=splitv(rt,v),b=splitv(a.fir,v-1);
        if(!b.sec||!(--cnt[b.sec])) return rt=merge(b.fir,a.sec);
        return sz[b.sec]--,rt=merge(merge(b.fir,b.sec),a.sec);
    }
    inline int kth(int k)
    {
        pii t=splitk(rt,k);int x=t.fir;
        while(ch[x][1]) x=ch[x][1];
        return rt=merge(t.fir,t.sec),val[x];
    }
    inline int pre(int v)
    {
        pii t=splitv(rt,v-1);int x=t.fir;
        while(ch[x][1]) x=ch[x][1];
        return rt=merge(t.fir,t.sec),val[x];
    }
    inline int post(int v)
    {
        pii t=splitv(rt,v);int x=t.sec;
        while(ch[x][0]) x=ch[x][0];
        return rt=merge(t.fir,t.sec),val[x];
    }
    inline int rank(int v)
    {
        pii a=splitv(rt,v),b=splitv(a.fir,v-1);
        int ans=sz[b.fir]+(b.sec>0);
        return rt=merge(merge(b.fir,b.sec),a.sec),ans;
    }
}s;
int main()
{
    for(int n=inn();n;n--) switch(inn())
    {
        case 1:s.insert(inn());break;
        case 2:s.del(inn());break;
        case 3:printf("%d\n",s.rank(inn()));break;
        case 4:printf("%d\n",s.kth(inn()));break;
        case 5:printf("%d\n",s.pre(inn()));break;
        case 6:printf("%d\n",s.post(inn()));break;
        default:printf("TAT\n");
    }
    return 0;
}

bzoj 3223

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<utility>
#include<climits>
#define gc getchar()
#define ull unsigned long long
#define N 100010
#define mp make_pair
#define fir first
#define sec second
using namespace std;
typedef pair<int,int> pii;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
int rt,node_cnt,ch[N][2],rev[N],val[N],key[N],sz[N],ans[N],c;
struct Rand{
    ull x;Rand(){ x=0; }
    inline ull operator()() { return (x*=998244353)^=1000000007; }
}rnd;
inline int new_node(int v,int x=0) { return x=++node_cnt,val[x]=v,key[x]=rnd(),sz[x]=1,x; }
inline int push_up(int x) { return sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; }
inline int setc(int x,int y,int z) { return ch[x][z]=y,push_up(x); }
inline int push_down(int x)
{
    if(!rev[x]) return 0;
    if(ch[x][0]) rev[ch[x][0]]^=1;
    if(ch[x][1]) rev[ch[x][1]]^=1;
    return swap(ch[x][0],ch[x][1]),rev[x]=0;
}
int merge(int x,int y)
{
    if(!x||!y) return x+y;push_down(x),push_down(y);
    if(key[x]<key[y]) return setc(x,merge(ch[x][1],y),1),x;
    else return setc(y,merge(x,ch[y][0]),0),y;return 0;
}
pii split(int x,int k)
{
    if(!x||!k) return mp(0,x);pii t;push_down(x);
    if(k<=sz[ch[x][0]]) return t=split(ch[x][0],k),setc(x,t.sec,0),mp(t.fir,x);
    else return t=split(ch[x][1],k-sz[ch[x][0]]-1),setc(x,t.fir,1),mp(x,t.sec);
}
inline int reverse(int l,int r)
{
    pii a=split(rt,r),b=split(a.fir,l-1);
    return rev[b.sec]^=1,rt=merge(merge(b.fir,b.sec),a.sec);
}
int build(int a,int b)
{
    if(a>b) return 0;int c=(a+b)>>1,x=new_node(c);
    return setc(x,build(a,c-1),0),setc(x,build(c+1,b),1),x;
}
int getans(int x) { return x?(push_down(x),getans(ch[x][0]),ans[++c]=val[x],getans(ch[x][1])):0; }
int main()
{
    int n=inn(),m=inn();rt=build(1,n);
    for(int l,r;m;m--) l=inn(),r=inn(),reverse(l,r);
    getans(rt);
    for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    return !printf("\n");
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/82380816