【BZOJ 3223】 文艺平衡树 (splay 板子)

来源:互联网 发布:植物生长算法 编辑:程序博客网 时间:2024/05/20 11:21

准备学lct,于是重学splay。

静态splay

//Au: Hany01//Prob: Splay//Date: Dec 3rd, 2017//Email: hany01@foxmail.com#include<bits/stdc++.h>using namespace std;typedef long long LL;typedef pair<int, int> PII;typedef vector<int> VI;#define For(i , j , k) for (int i = (j) , i##_end_ = (k) ; i <= i##_end_ ; ++ i)#define Fordown(i , j , k) for (int i = (j) , i##_end_ = (k) ; i >= i##_end_ ; -- i)#define Set(a , b) memset(a , b , sizeof(a))#define pb(a) push_back(a)#define mp(a, b) make_pair(a, b)#define ALL(a) (a).begin(), (a).end()#define SZ(a) ((int)(a).size())#define fir first#define sec second#define INF (0x3f3f3f3f)#define INF1 (2139062143)#define Mod (1000000007)#ifdef hany01#define debug(...) fprintf(stderr , __VA_ARGS__)#else#define debug(...)#endiftemplate <typename T> inline bool chkmax(T &a , T b) { return a < b ? (a = b , 1) : 0; }template <typename T> inline bool chkmin(T &a , T b) { return b < a ? (a = b , 1) : 0; }inline int read(){    register int _ , __; register char c_;    for (_ = 0 , __ = 1 , c_ = getchar() ; !isdigit(c_) ; c_ = getchar()) if (c_ == '-') __ = -1;    for ( ; isdigit(c_) ; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);    return _ * __;}inline void File(){#ifdef hany01    freopen("splay.in" , "r" , stdin);    freopen("splay.out" , "w" , stdout);#endif}const int maxn = 100005;int sz[maxn], va[maxn], ch[maxn][2], flag[maxn], n, m, cnt, rt;inline void maintain(int o) { sz[o] = sz[ch[o][0]] + sz[ch[o][1]] + 1; }inline void pushdown(int x) {    if (flag[x]) {        flag[x] = 0; swap(ch[x][0], ch[x][1]);        flag[ch[x][0]] ^= 1; flag[ch[x][1]] ^= 1;    }}int build(int n){    if (!n) return 0;    int lc = build(n >> 1);    int now = ++ cnt;    va[now] = now - 1;    ch[now][0] = lc;    ch[now][1] = build(n - (n >> 1) - 1);    maintain(now);    return now;}inline void Init(){    n = read(); m = read();    rt = build(n + 1);}inline int cmp(int x, int k){    if (k == sz[ch[x][0]] + 1) return -1;    return k > sz[ch[x][0]];}inline void rotate(int &o, int d){    int k = ch[o][d ^ 1];    ch[o][d ^ 1] = ch[k][d]; ch[k][d] = o;    maintain(o); maintain(k); o = k;}void splay(int &o, int k){    pushdown(o);    register int d = cmp(o, k);    if (d == -1) return ;    if (d) k -= sz[ch[o][0]] + 1;    int p = ch[o][d];    pushdown(p);    int d2 = cmp(p, k);    if (d2 >= 0)    {        int k2 = d2 ? k - sz[ch[p][0]] - 1 : k;        splay(ch[p][d2], k2);        if (d == d2) rotate(o, d ^ 1); else rotate(ch[o][d], d);    }    rotate(o, d ^ 1);}void DEBUG(int x){    if (!x) return ;    pushdown(x);    DEBUG(ch[x][0]);    printf("%d ", va[x]);    DEBUG(ch[x][1]);}inline int merge(int x, int y){//  cout << x << ' ' << sz[x] << endl;//  DEBUG(x);//  putchar('\n');    splay(x, sz[x]);    ch[x][1] = y;    maintain(x);    return x;}inline void split(int o, int k, int &l, int &r){    splay(o, k);    l = o;    r = ch[o][1];    ch[l][1] = 0;    maintain(l);}inline void Solve(){    while (m --)    {        register int l, r;        l = read(); r = read();        register int le, ri, md, o;        split(rt, l, le, o);        split(o, r - l + 1, md, ri);        flag[md] ^= 1;        rt = merge(merge(le, md), ri);    }}void Print(int x){    if (!x) return ;    pushdown(x);    Print(ch[x][0]);    if (va[x]) printf("%d ", va[x]);    Print(ch[x][1]);}int main(){    File();    Init();    Solve();    Print(rt);    return 0;}//夫子何为者,栖栖一代中。//地犹鄹氏邑,宅即鲁王宫。//叹凤嗟身否,伤麟怨道穷。//今看两楹奠,当与梦时同。//--唐玄宗《经邹鲁祭孔子而叹之》

动态splay

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#define For(i , j , k) for (int i = (int)(j) ; i <= (int)(k) ; ++ i)#define Fordown(i , j , k) for (int i = (int)(j) ; i >= (int)(k) ; -- i)#define Set(a , b) memset(a , b , sizeof(a))using namespace std;const int maxn = 100010;struct node{    node *ch[2];    int num , s , flag;    node()    {        s = flag = num = 0;    }}*rt , *null;int n , m , nn , l , r , ans[maxn] , anss;inline int cmp(node *o , int k){    int d = k - o->ch[0]->s;    if (d == 1)        return -1;    return d <= 0 ? 0 : 1;}inline void maintain(node* &o){    o -> s = 1 + o -> ch[0] -> s + o -> ch[1] -> s;}inline void pushdown(node* &o){    if (o -> flag)    {        o -> flag = 0;        swap(o -> ch[0] , o -> ch[1]);        o -> ch[0] -> flag ^= 1;        o -> ch[1] -> flag ^= 1;    }}node* build(int k){    if (!k)        return null;    node *o = new node;    o -> ch[0] = build(k / 2);    o -> num = ++ n;    o -> ch[1] = build(k - k / 2 - 1);    o -> flag = o -> s = 0;    maintain(o);    return o;}void Init(){    scanf("%d%d" , &nn , &m);    null = new node;    n = 0;    rt = build(nn + 1);}void rotate(node* &o , int d){    node *k;    k = o -> ch[d ^ 1];    o -> ch[d ^ 1] = k -> ch[d];    k -> ch[d] = o;    maintain(o);    maintain(k);    o = k;}void splay(node* &o , int k){    pushdown(o);    int d = cmp(o , k);    if (d == 1)        k -= o->ch[0]->s + 1;    if (d >= 0)    {        node *p = o -> ch[d];        pushdown(p);        int d2 = cmp(p , k);        int k2 = k;        if (d2)            k2 -= p->ch[0]->s + 1;        if (d2 != -1)        {            splay(p->ch[d2] , k2);            if (d == d2)                rotate(o , d ^ 1);            else                rotate(o->ch[d] , d);        }        rotate(o , d ^ 1);    }}node* merge(node* l , node* r){    splay(l , l -> s);    l -> ch[1] = r;    maintain(l);    return l;}void split(node* rt , int k , node* &l , node* &r){    splay(rt , k);    l = rt;    r = rt -> ch[1];    rt -> ch[1] = null;    maintain(l);}void Solve(){    while (m --)    {        scanf("%d%d" , &l , &r);        node *le , *ri , *mi , *o;        split(rt , l , le , o);        split(o , r - l + 1 , mi , ri);        mi -> flag ^= 1;        rt = merge(merge(le , mi) , ri);    }}void Print(node *u){    if (u == null)        return ;    pushdown(u);    Print(u -> ch[0]);    ans[anss ++] = u -> num;    Print(u -> ch[1]);}int main(){#ifndef ONLINE_JUDGE    freopen("Splay.in" , "r" , stdin);    freopen("Splay1.out" , "w" , stdout);#endif    Init();    Solve();    Print(rt);    For(i , 1 , anss - 1)        printf("%d " , ans[i] - 1);    return 0;}//风吹柳花满店香,吴姬压酒唤客尝。//金陵子弟来相送,欲行不行各尽觞。//请君试问东流水,别意与之谁短长。//--李白《金陵酒肆留别》

另一种简洁的旋转操作(保存父节点)

inline void rotate(int x){    int f = fa[x], gf = fa[f], d = dir(x), gd = dir(f);    //The followed 2 lines can't be reversed!!    //Because if you reverse them, the second line will change the value of ch[x][d^1];    fa[ch[f][d] = ch[x][d ^ 1]] = f;//!    ch[fa[f] = x][d ^ 1] = f;//!    fa[ch[gf][gd] = x] = gf;    maintain(f); maintain(x);}
原创粉丝点击