后3个点T了

P3391 【模板】文艺平衡树

Stream月 @ 2020-01-16 21:05:40

提交记录

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
typedef long long ll;

#define $(i, a, n) for(int i = a; i <= n; ++i)

using namespace std;

inline ll read() {
    ll ans = 0;
    char ch = getchar(), last = ' ';
    while (ch < '0' || ch > '9') last = ch, ch = getchar();
    while (ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0', ch = getchar();
    if (last == '-') return -ans;
    return ans;
}

const int INF = 0x3f3f3f3f;

const int N = 5e5 + 5;
int root, pool;
struct node{
    int size, fa, son[2], col, data, cnt;
}t[N];
int n, m, l, r;
int which(int x) {
    return t[t[x].fa].son[1] == x;
}
void pushup(int x) {
    t[x].size = t[t[x].son[0]].size + t[t[x].son[1]].size + t[x].cnt;
}
void pushdown(int x) {
    if (t[x].col) {
        swap(t[x].son[1], t[x].son[0]);
        if (t[x].son[0]) t[t[x].son[0]].col ^= 1;
        if (t[x].son[1]) t[t[x].son[1]].col ^= 1;
        t[x].col = 0;
    }
}
void rotate(int x) {
    int y = t[x].fa, z = t[y].fa;
    int b = which(x), c = which(y);
    int a = t[x].son[!b];
    if (z) t[z].son[c] = x;
    else root = x;
    t[x].fa = z;
    if (a) t[a].fa = y;
    t[y].son[b] = a;
    t[y].fa = x;
    t[x].son[!b] = y;
    pushup(y);
    pushup(x);
}

void splay(int x, int i) {
    int y, z;
    while (t[x].fa != i) {
        y = t[x].fa, z = t[y].fa;
        if (z == i) {
            rotate(x);
            return;
        } else if (which(x) == which(y)) {
            rotate(y), rotate(x);
        } else rotate(x), rotate(x);
    }
}

void insert(int &x, int v) {
    if (!x) {
        x = ++pool;
        t[x].size = t[x].cnt = 1;
        t[x].data = v;
        t[x].col = 0;
        return;
    } 
    if (v == t[x].data) {
        t[x].cnt++, t[x].size++;
        return;
    }
    if (v < t[x].data) {
        insert(t[x].son[0], v);
        t[t[x].son[0]].fa = x;
    } else {
        insert(t[x].son[1], v);
        t[t[x].son[1]].fa = x;
    }
    pushup(x);
}

int kth(int x, int k) {
    pushdown(x);
    int l = t[x].son[0];
    if (t[l].size >= k) return kth(l, k);
    else if (k == t[l].size + 1) return x;
    else return kth(t[x].son[1], k - t[l].size - 1);
}
int kth(int k) {
    int now = root;
    while(true) {
        pushdown(now);
        if (t[t[now].son[0]].size >= k) {
            now = t[now].son[0];
        } else {
            k -= t[t[now].son[0]].size + 1;
            if (!k) return now;
            else now = t[now].son[1];
        }
    }
}
void resverse(int l, int r) {
    l = l - 1, r = r + 1;
    l = kth(l), r = kth(r);
    splay(l, 0);
    splay(r, l);
    int pos =  t[root].son[1];
    pos = t[pos].son[0];
    t[pos].col ^= 1;
}

void print(int x) {
    pushdown(x);
    if (t[x].son[0]) print(t[x].son[0]);
    if (t[x].data != -INF && t[x].data != INF) printf("%d ", t[x].data);
    if (t[x].son[1]) print(t[x].son[1]);
}
int a[N];
int main() {
    //freopen("testdata.in", "r", stdin);
    //freopen("ans.out", "w", stdout);
    n = read(), m = read();
    for (int i = 2; i <= n + 1; ++i) a[i] = i - 1;
    a[1] = -INF;
    a[n + 2] = INF;
    for (int i = 1; i <= n + 2; ++i) insert(root, a[i]);
    for (int i = 1; i <= m; ++i) {
        l = read(), r = read();
        resverse(l + 1, r + 1);
    } 
    print(root);
    return 0;
}

by 皎月半洒花 @ 2020-01-16 21:15:57

似乎是没有定期splay?试试多splay几次?


by hly1204 @ 2020-01-16 21:19:44

不要用insert直接用线段树那样构造就行了


by Stream月 @ 2020-01-17 07:55:57

@hly1204 现在A了,为什么单点插入会T呢


by hly1204 @ 2020-01-17 13:28:04

@Stream月 插入也可以,但是每次插入之后要伸展那个节点,就是对于splay tree来说每次访问都要伸展last access的那个节点才行。这题的话你伸展之后下一次插入就直接在右子树插入了,复杂度是很低的。


by Stream月 @ 2020-01-17 18:17:35

@hly1204 懂了,多谢


|