文艺线段树Splay为什么超时了?

P3391 【模板】文艺平衡树

muvum @ 2021-09-15 22:06:50

#include <cstdio>
#include <iostream>

template<typename Tp>
inline Tp read() {
    Tp x = 0; char c = getchar();
    while (c < '0' || c > '9') c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    return x;
}

template <typename Tp>
inline void swap(Tp &x, Tp &y) {
    Tp t = x; x = y; y = t;
}

const int MAXN = 1e5 + 1;

int n, m, root, tot;
int sz[MAXN], v[MAXN], ch[MAXN][2], fa[MAXN], tag[MAXN];

inline int type(int x) {
    return x == ch[fa[x]][1];
}

inline void maintain(int x) {
    if (x) {
        sz[x] = 1;
        if (ch[x][0]) sz[x] += sz[ch[x][0]];
        if (ch[x][1]) sz[x] += sz[ch[x][1]];
    }
}

inline void pushdown(int x) {
    if (x && tag[x]) {
        if (ch[x][0]) tag[ch[x][0]] ^= 1;
        if (ch[x][1]) tag[ch[x][1]] ^= 1;
        std::swap(ch[x][0], ch[x][1]);
        tag[x] = 0;
    }
}//下穿旋转标记

void rotate(int x) {
    int y = fa[x], z = fa[y], t = type(x);
    pushdown(x); pushdown(y);
    ch[y][t] = ch[x][t^1];
    if (ch[x][t^1]) fa[ch[x][t^1]] = y;
    fa[y] = x; fa[x] = z;
    ch[x][t^1] = y;
    if (z) ch[z][y==ch[z][1]] = x;
    maintain(y);
}

void splay(int x, int goal) {
    for (int f=fa[x]; (f=fa[x])!=goal; rotate(x))
        if (fa[f] != goal) rotate(type(x) == type(f) ? f : x);
    if (goal == 0) root = x;
}

int find(int x) {
    int cur = root;
    for(;;) {
        pushdown(cur);
        if (ch[cur][0] && x <= sz[ch[cur][0]]) cur = ch[cur][0];
        else {
            x -= sz[ch[cur][0]] + 1;
            if (!x) return cur;
            cur = ch[cur][1];
        }
    }
} //查找排在第x个的节点编号

void reverse(int L, int R) {
    int s = find(L - 1), t = find(R + 1);
    splay(s, 0); splay(t, s);
    //把L-1,R+1两个节点转到根部
    int pos = ch[ch[root][1]][0];
    tag[pos] ^= 1;//打标记
}

int build(int s, int t, int f) {
    if (s > t) return 0;
    int mid = (s + t) >> 1, cur = ++tot;
    v[cur] = mid;
    fa[cur] = f;
    ch[cur][0] = build(s, mid - 1, cur);
    ch[cur][1] = build(mid + 1, t, cur);
    maintain(cur);
    return cur;
}//因为是有序的,所以可以用递归建树

void output(int cur) {
    if (!cur) return;
    pushdown(cur);
    output(ch[cur][0]);
    if (v[cur] > 1 && v[cur] < n + 2)
        std::cout << v[cur] - 1 << ' ';
    //因为把0和n+1也加进来了所以原来的1->2,2->3等等,输出时减回来
    output(ch[cur][1]);
}//输出中序遍历

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr); std::cout.tie(nullptr);

    n = read<int>(); m = read<int>();
    root = build(1, n + 2, 0);
    for (int i=1; i<=m; ++i) {
        int L = read<int>(), R = read<int>();
        reverse(L + 1, R + 1);
    }
    output(root); std::cout << std::endl;
    return 0;
}

|