RE:从零开始的数据结构生活 第二弹

继昨天RE:从零开始的数据结构生活之后,我陷入splay中不能自拔,所以说今天又学了下splay的区间(翻转)操作。
不得不说,一颗赛艇~

每当要翻转区间[l,r]时,先将l-1转到根的位置,再把r+1转到根的位置,则根的左子树就是要翻转的区间,然后交换左右儿子的指针就好了

以BZOJ 3223为例题, 贴一份模板

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int SZ = 1e6 + 10;
const int INF = 1e9;

struct node
{
    node *ch[2], *f;
    int v, sz, cnt;
    bool flag;

    void maintain()
    {
        sz = cnt + ch[1] -> sz + ch[0] -> sz;
    }

    int cmp(int x)
    {
        if(x == v) return -1;
        return x < v ? 0 : 1;
    }

    int dir()
    {
        return f -> ch[1] == this;
    }

    void setc(node *x, int d)
    {
        (ch[d] = x) -> f = this;
    }

    void pushdown();

}T[SZ], *root, *null;
int Tcnt, n, m;

void node :: pushdown()
{
    if(flag)
    {
        flag = 0;
        if(ch[1] != null) ch[1] -> flag ^= 1;
        if(ch[0] != null) ch[0] -> flag ^= 1;
        swap(ch[0], ch[1]);
    }
}

node *newnode(int x, node *f)
{
    node *k = T + (++Tcnt);
    k -> sz = k -> cnt = 1;
    k -> v = x;
    k -> ch[0] = k -> ch[1] = null;
    k -> flag = 0;
    k -> f = f;
    return k;
}

void rotate(node *p)
{
    p -> f -> pushdown();
    p -> pushdown();
    node *fa = p -> f;
    int d = p -> dir();
    fa -> f -> setc(p, fa -> dir());
    fa -> setc(p -> ch[d ^ 1], d);
    fa -> maintain();
    p -> setc(fa, d ^ 1);
    p -> maintain();
    if(fa == root) root = p;
}

void splay(node *p, node *rt = null)
{
    while(p -> f != rt)
    {
        p -> pushdown();
        if(p -> f -> f == rt) rotate(p);
        else
        {
            if(p -> dir() == p -> f -> dir()) rotate(p -> f), rotate(p);
            else rotate(p), rotate(p);
        }
    }
}

node* find(node *p, int k)
{
    while(p != null)
    {
        p -> pushdown();
        int l = p -> ch[0] -> sz + 1;
        int r = p -> ch[0] -> sz + p -> cnt;
        if(l <= k && k <= r) return p;
        if(k > r) k -= r, p = p -> ch[1];
        else p = p -> ch[0];  
    }
}

void reverse(node *p, int l, int r)
{
    l++; r++;
    node *pre = find(root, l - 1);
    node *suf = find(root, r + 1);
    splay(pre);
    splay(suf, root);
    root -> ch[1] -> ch[0] -> flag ^= 1;
}

void build(node* &p, int l, int r, node *fa) //1-n插入到splay中 
{
    if(l > r) return;
    int mid = (l + r) >> 1;
    p = newnode(mid, fa);
    build(p -> ch[0], l, mid - 1, p);
    build(p -> ch[1], mid + 1, r, p);
    p -> maintain();
}

void init()
{
    null = newnode(-INF, null);
    null -> sz = null -> cnt = 0;

    root = newnode(-INF, null);
    root -> ch[1] = newnode(INF, root);
    build(root -> ch[1] -> ch[0], 1, n, root -> ch[1]);
    root -> ch[1] -> maintain();
    root -> maintain();
}

int main()
{
    scanf("%d%d", &n, &m);
    init();
    int l, r;
    while(m--)
    {
        scanf("%d%d", &l, &r);
        reverse(root, l, r);
    } 
    for(int i = 1; i <= n; i++)
        printf("%d ", (find(root, i + 1)) -> v);
    return 0;
}
posted @ 2016-09-29 11:15  Loi_Vampire  阅读(94)  评论(0编辑  收藏  举报