萌新文明刚形成5000年,求助Splay模板【实现正常,码风好看】
查看原帖
萌新文明刚形成5000年,求助Splay模板【实现正常,码风好看】
387009
wangbinfeng楼主2023/12/25 22:10

实现正常因为照着视频打的,码风好看是让ChatGPT帮忙改的。

// Splay普通平衡树

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

#define int long long

inline int read() {
    int x = 0, f = 1;
    char c;
    for (c = getchar(); c < '0' || c > '9'; c = getchar())
        if (c == '-') f = -f;
    for (; c >= '0' && c <= '9'; c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    return x * f;
}

class node {
public:
    int s[2], fa, val, cnt, size;

    node() = default;

    void init(int p, int v) {
        fa = p, val = v, cnt = size = 1;
    }
};

node tr[1000009];
int root, idx;

inline void pushup(int x) {
    tr[x].size = tr[tr[x].s[0]].size + tr[tr[x].s[1]].size + tr[x].cnt;
}

inline void rotate(int x) { // 旋转※包括左旋和右旋
    int y = tr[x].fa, z = tr[y].fa; // y=father;z=grandfather
    int k = tr[y].s[1] == x; // k=x is y's which son
    tr[y].s[k] = tr[x].s[k ^ 1];
    tr[tr[x].s[k ^ 1]].fa = y;
    tr[x].s[k ^ 1] = y;
    tr[y].fa = x;
    tr[z].s[tr[z].s[1] == y] = x;
    tr[x].fa = z;
    pushup(y), pushup(x);
}

inline void splay(int x, int k) { // 伸展※核心 (目标:使x成为k的儿子)
    while (tr[x].fa != k) {
        int y = tr[x].fa, z = tr[y].fa;
        if (z != k)
            if ((tr[y].s[0] == x && tr[y].s[0] != y) || (tr[y].s[0] != x && tr[y].s[0] == y))
                rotate(x);
            else
                rotate(y);
        rotate(x);
    }
    if (k == 0) root = x;
}

inline void find(int v) {
    int x = root;
    while (tr[x].s[v > tr[x].val] && v != tr[x].val) x = tr[x].s[v > tr[x].val];
    splay(x, 0);
}

inline int getpre(int v) {
    find(v);
    int x = root;
    if (tr[x].val < v) return x;
    x = tr[x].s[0];
    while (tr[x].s[1]) x = tr[x].s[1];
    return x;
}

inline int getsuc(int v) {
    find(v);
    int x = root;
    if (tr[x].val > v) return x;
    x = tr[x].s[1];
    while (tr[x].s[0]) x = tr[x].s[0];
    return x;
}

inline void del(int v) {
    int pre = getpre(v), suc = getsuc(v);
    splay(pre, 0), splay(suc, pre);
    int del = tr[suc].s[0];
    if (tr[del].cnt > 1) tr[del].cnt--, splay(del, 0);
    else tr[suc].s[0] = 0, splay(suc, 0);
}

inline int getrank(int v) {
    find(v);
    return tr[tr[root].s[0]].size;
}

inline int getval(int k) {
    int x = root;
    while (true) {
        int y = tr[x].s[0];
        if (tr[y].size + tr[x].cnt < k) {
            k -= tr[y].size + tr[x].cnt;
            x = tr[x].s[1];
        } else {
            if (tr[y].size >= k) x = tr[x].s[0];
            else break;
        }
    }
    splay(x, 0);
    return tr[x].val;
}

inline void insert(int v) {
    int x = root, p = 0;
    while (x && tr[x].val != v) p = x, x = tr[x].s[v > tr[x].val];
    if (x) tr[x].cnt++;
    else {
        x = ++idx;
        tr[p].s[v > tr[p].val] = x;
        tr[x].init(p, v);
    }
    splay(x, 0);
}

signed main() {
    insert(0x80000000), insert(0x7fffffff);
    int n = read();
    while (n--) {
        int op = read(), x = read();
        switch (op) {
            case 1:
                insert(x);
                break;
            case 2:
                del(x);
                break;
            case 3:
                printf("%lld\n", getrank(x));
                break;
            case 4:
                printf("%lld\n", getval(x + 1));
                break;
            case 5:
                printf("%lld\n", tr[getpre(x)].val);
                break;
            case 6:
                printf("%lld\n", tr[getsuc(x)].val);
                break;
        }
    }
}

显然连样例都没过,所以应该比较容易查错。

^_^

2023/12/25 22:10
加载中...