1. 程式人生 > >3223 Tyvj 1729 文藝平衡樹——splay區間翻轉

3223 Tyvj 1729 文藝平衡樹——splay區間翻轉

剛開始學spaly,所以一上來不會打標記,後來想了想splay的區間操作和線段樹其實基本一樣。

lazy標記的下推注意一下, update時如果直接進行splay操作的話會因lazy標記沒有下推而出錯,正確做法是在splay操作前先進行一個區間第k大查詢操作(因為區間反轉破壞了二叉搜尋樹的性質,所以我們只能進行區間第k大的查詢來輔助下推)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 10;
int n, m;
struct Splay {
    int sz, root, fa[maxn], ch[maxn][2], key[maxn], size[maxn], lazy[maxn];
    void newnode(int x, int f, int v) { fa[x] = f, key[x] = v; size[x] = 1; }
    void pushup(int x) {
        if (!x) return;
        size[x] = size[ch[x][0]] + size[ch[x][1]] + 1;
    }
    void pushdown(int x) {
        if (!x || !lazy[x]) return;
        lazy[ch[x][0]] ^= 1;
        lazy[ch[x][1]] ^= 1;
        swap(ch[ch[x][0]][0], ch[ch[x][0]][1]);
        swap(ch[ch[x][1]][0], ch[ch[x][1]][1]);
        lazy[x] = 0;
    }
    int build(int l, int r, int f) {
        if (l > r) return 0;
        int mid = (l + r) >> 1;
        int x = ++sz;
        newnode(x, f, mid);
        ch[x][0] = build(l, mid-1, x);
        ch[x][1] = build(mid+1, r, x);
        pushup(x);
        return x;
    }
    int pos(int x) {
        return ch[fa[x]][1] == x;
    }
    void rotate(int x) {
        int y = fa[x], z = fa[y], posx = pos(x), posy = pos(y);
        ch[y][posx] = ch[x][posx^1]; fa[ch[y][posx]] = y;
        ch[x][posx^1] = y; fa[y] = x;
        fa[x] = z; if (z) ch[z][posy] = x;
        pushup(y); pushup(x);
    }
    void splay(int x, int y) {
        for (int f; (f=fa[x]) != y; rotate(x)) {
            if (fa[f] != y) rotate(pos(x) == pos(f)?f:x);
        }
        if (y == 0) root = x;
    }
    int kth(int x, int k) {
        pushdown(x);
        if (size[ch[x][0]]+1 == k) return x;
        if (size[ch[x][0]]+1 > k) return kth(ch[x][0], k);
        else return kth(ch[x][1], k-size[ch[x][0]]-1);
    }
    void update(int l, int r) {
        int x = kth(root, l), y = kth(root, r);
        splay(x, 0); splay(y, x);
        int z = ch[y][0];
        swap(ch[z][0], ch[z][1]);
        lazy[z] ^= 1;
    }
    void query(int x) {
        if (!x) return;
        pushdown(x);
        query(ch[x][0]);
        if (1 <= key[x]-1 && key[x]-1 <= n) printf("%d ", key[x]-1);
        query(ch[x][1]);
    }
}ac;
int main() {
    int l, r;
    scanf("%d%d", &n, &m);
    ac.root = ac.build(1, n+2, 0);
    while (m--) {
        scanf("%d%d", &l, &r);
        l++, r++;
        ac.update(l-1, r+1);
    }
    ac.query(ac.root);
    printf("\n");
    return 0;
}