20pts 萌新求助 splay!!

P6136 【模板】普通平衡树(数据加强版)

Kevin_Zhen @ 2021-06-29 18:29:27

只过了 #3 和 #4,而且不知道为什么范围 1e5n 数组开 1e6 #4 都会 re

#include <iostream>
#include <cstdio>
using namespace std;

const int maxn = 2e6 + 10;
const int inf = 0x3f3f3f3f;

int n, m, rt, tot, lst, ans;
int val[maxn], ch[maxn][2], fa[maxn];
int cnt[maxn], siz[maxn];

inline void update(int u) { siz[u] = siz[ch[u][0]] + siz[ch[u][1]] + cnt[u]; }
inline int newnode(int x) {
    val[++tot] = x;
    cnt[tot] = siz[tot] = 1;
    fa[tot] = ch[tot][0] = ch[tot][1] = 0;
    return tot;
}
inline void init() {
    tot = 0;
    newnode(-inf); newnode(inf);
    rt = 1; siz[1] = 2;
    ch[1][1] = 2; fa[2] = 1;
}

inline void rotate(int u) {
    int f = fa[u], gf = fa[f], k = (ch[f][1] == u);
    ch[f][k] = ch[u][k ^ 1]; fa[ch[u][k ^ 1]] = f;
    ch[u][k ^ 1] = f; fa[f] = u;
    ch[gf][ch[gf][1] == f] = u; fa[u] = gf;
    update(f); update(u);
}

inline void splay(int u, int goal = 0) {
    if (!goal) rt = u;
    while (fa[u] != goal) {
        int f = fa[u], gf = fa[f];
        if (gf != goal) (ch[f][1] == u) ^ (ch[gf][1] == f) ? rotate(u) : rotate(f);
        rotate(u);
    }
}

inline void find(int x) {
    int p = rt;
    while (val[p] != x && ch[p][x > val[p]]) p = ch[p][x > val[p]];
    splay(p);
}

inline int pre(int x) {//找的是结点编号 
    find(x);
    if (val[rt] < x) return rt;
    int p = ch[rt][0];
    while (ch[p][1]) p = ch[p][1];
    return splay(p), p;
} 
inline int suc(int x) {//号 
    find(x);
    if (val[rt] > x) return rt;
    int p = ch[rt][1];
    while (ch[p][0]) p = ch[p][0];
    return splay(p), p;
}

inline int kth(int k) {//号 
    int p = rt;
    while (1) {
        int v = ch[p][0];
        if (siz[v] + cnt[p] < k) k -= siz[v] + cnt[p], p = ch[p][1];
        else {
            if (siz[v] < k) return splay(p), p;
            else p = v;
        }
    }
}

inline void ins(int x) {
    int p = rt, f = 0;
    while (p && val[p] != x) f = p, p = ch[p][x > val[p]];
    if (!p) {
        p = newnode(x);
        ch[f][x > val[f]] = p;
        fa[p] = f;
    } else ++cnt[p];
    splay(p);
}
inline void del(int x) {
    int xp = pre(x), xs = suc(x);
    splay(xp); splay(xs, xp);
    int p = ch[xs][0];
    if (--cnt[p]) splay(p);
    else ch[xs][0] = 0, update(xs), update(xp);
}

inline int rk(int x) {
    ins(x); find(x);
    int res = siz[ch[rt][0]] + 1;
    return del(x), res;
}

int main() {
    init();
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        int t; scanf("%d", &t);
        ins(t);
    }
    while (m--) {
        int opt, x; scanf("%d%d", &opt, &x); x ^= lst;
        if (opt == 1) ins(x);
        else if (opt == 2) del(x);
        else if (opt == 3) ans ^= lst = rk(x) - 1;
        else if (opt == 4) ans ^= lst = val[kth(x + 1)];
        else if (opt == 5) ans ^= lst = val[pre(x)];
        else if (opt == 6) ans ^= lst = val[suc(x)];
    }
    printf("%d", ans);
    return 0;
}

by Kevin_Zhen @ 2021-06-30 22:37:52

完结咯,告诫后人:


by Kevin_Zhen @ 2021-06-30 22:39:06

另外,n 是初始数列的长度,后续可能会插入新的数,所以数组不能只开 1e6


by lcyxds @ 2021-07-04 20:59:40

@九章 ?偶然发现你的代码交上去改成spaly居然所有点都更快


by Kevin_Zhen @ 2021-07-05 21:45:09

@lcyxds 害怕!可能是因为 spaly 是信仰( /jk


|