【BZOJ 3223】 文艺平衡树

【题目链接】

          点击打开链接

【算法】

         本题是splay区间操作的模板题

         我们每个点的权值设为”当前在序列中的排名“,根据二叉排序树的性质,这棵树的中序遍历就是当前序列

         如果我们要获得一段区间[l,r],那么我们将l-1splay到根节点,将r+1splay到根节点的右子树的根,我们发现,根节点

         的右节点的左子树就是区间[l,r]

         对于翻转操作,我们其实只需将“根节点的右节点的左子树”这棵树不断地进行左右子树交换就可以了,但是,为了避免

         交换次数太多,我们可以像线段树那样,每个点都存一个懒惰标记

【代码】

         

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100000

int i,N,M,l,r;

template <typename T> inline void read(T &x) {
        int f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; }
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
}

template <typename T> inline void write(T x) {
    if (x < 0) { putchar('-'); x = -x; }
    if (x > 9) write(x/10);
    putchar(x%10+'0');
}

template <typename T> inline void writeln(T x) {
    write(x);
    puts("");
}

struct Splay {
        int root,total;
        struct Node {
                int size,val,son[2],fa;
                bool rev;
        } Tree[MAXN+10];
        inline bool get(int x) {
                return Tree[Tree[x].fa].son[1] == x;
        }
        inline void update(int index) {
                Tree[index].size = Tree[Tree[index].son[0]].size + Tree[Tree[index].son[1]].size + 1;
        }
        inline void build(int index,int l,int r) {
                int mid = (l + r) >> 1;
                Tree[index].rev = false;
                Tree[index].val = mid;
                Tree[index].size = 1;
                if (l == r) return;
                if (l <= mid - 1) {
                        ++total;
                        Tree[index].son[0] = total;
                        Tree[total].fa = index;
                        build(total,l,mid-1);
                        Tree[index].size += Tree[Tree[index].son[0]].size;
                }
                if (mid + 1 <= r) {
                        ++total;
                        Tree[index].son[1] = total;
                        Tree[total].fa = index;
                        build(total,mid+1,r);
                        Tree[index].size += Tree[Tree[index].son[1]].size;
                }
        }
        inline void rotate(int x) {
                int f = Tree[x].fa,g = Tree[f].fa,
                tmpx = get(x),tmpf = get(f);
                if (Tree[f].rev) pushdown(f);
                if (Tree[x].rev) pushdown(x);
                if (!f) return;
                Tree[f].son[tmpx] = Tree[x].son[tmpx^1];
                if (Tree[x].son[tmpx^1]) Tree[Tree[x].son[tmpx^1]].fa = f;
                Tree[x].son[tmpx^1] = f;
                Tree[f].fa = x;
                Tree[x].fa = g;
                if (g) Tree[g].son[tmpf] = x;
                update(f);
                update(x);
        }
        inline void splay(int x) {
                int f;
                for (f = Tree[x].fa; (f = Tree[x].fa); rotate(x)) 
                        if (Tree[f].fa) rotate(get(x) == get(f) ? f : x);  
                root = x;
        }
        inline void splayII(int x) {
                int f;
                for (f = Tree[x].fa; (f = Tree[x].fa) != root; rotate(x)) {
                        if (Tree[f].fa != root) rotate(get(x) == get(f) ? f : x);  
                }
        }
        inline void pushdown(int index) {
                swap(Tree[index].son[0],Tree[index].son[1]);
                Tree[Tree[index].son[0]].rev ^= 1;
                Tree[Tree[index].son[1]].rev ^= 1;
                Tree[index].rev = 0;
        }
        inline int query_pos(int x) {
                int index = root;
                while (true) {
                        if (Tree[index].rev) pushdown(index);
                        if (x <= Tree[Tree[index].son[0]].size) index = Tree[index].son[0];
                        else {
                                x -= Tree[Tree[index].son[0]].size;
                                if (x == 1) return index;
                                --x;
                                index = Tree[index].son[1];
                        }
                }
        }
        inline int query_val(int x) {
                int pos = query_pos(x);
                return Tree[pos].val;
        }
        inline void reverse(int l,int r) {
                int x = query_pos(l-1),
                        y = query_pos(r+1);
                splay(x); splayII(y);
                Tree[Tree[Tree[root].son[1]].son[0]].rev ^= 1;
        }
} T;

int main() {
        
        read(N); read(M);
        
        T.total = 1;
        T.root = 1;
        T.build(1,1,N+2);
        
        while (M--) {
                read(l); read(r);
                T.reverse(l+1,r+1);            
        }
        
        for (i = 2; i <= N + 1; i++) {
                if (i == 2) write(T.query_val(i)-1);
                else { putchar(' '); write(T.query_val(i)-1); }
        }
        putchar(' ');
        
        puts("");
        
        return 0;
    
}

 

posted @ 2018-03-03 10:50  evenbao  阅读(140)  评论(0编辑  收藏  举报