Splay树

2024-08-12

伸展树是一种高效率的BST,通过单旋、一字旋、之字旋等操作,实现数据的高效插入、删除

#include <bits/stdc++.h>
#define io cin.tie(0), cout.tie(0), ios::sync_with_stdio(false)
#define LL long long
#define ULL unsigned long long
#define EPS 1e-8
#define INF 0x7fffffff
#define SUB -INF - 1
using namespace std;
const int M = 100005;
int cnt, root;
struct node
{
    int fa, ls, rs, size;
    char val;
} t[M];
void update(int u)
{
    t[u].size = t[t[u].ls].size + t[t[u].rs].size + 1;
}
char str[M] = {0};
int build(int l, int r, int f)
{
    if (l > r)
        return 0;
    int mid = (l + r) >> 1;
    int cur = ++cnt;
    t[cur].fa = f;
    t[cur].val = str[mid];
    t[cur].ls = build(l, mid - 1, cur);
    t[cur].rs = build(mid + 1, r, cur);
    update(cur);
    return cur;
}
int get(int x)
{
    return t[t[x].fa].rs == x;
}
void rotate(int x)
{
    int f = t[x].fa, g = t[f].fa, son = get(x);
    if (son == 1)
    {
        t[f].rs = t[x].ls;
        if (t[f].rs)
            t[t[f].rs].fa = f;
    }
    else
    {
        t[f].ls = t[x].rs;
        if (t[f].ls)
            t[t[f].ls].fa = f;
    }
    t[f].fa = x;
    if (son == 1)
        t[x].ls = f;
    else
        t[x].rs = f;
    t[x].fa = g;
    if (g)
    {
        if (t[g].rs == f)
            t[g].rs = x;
        else
            t[g].ls = x;
    }
    update(f);
    update(x);
}
void splay(int x, int goal)
{
    if (goal == 0)
        root = x;
    while (1)
    {
        int f = t[x].fa, g = t[f].fa;
        if (f == goal)
            break;
        if (g != goal)
        {
            if (get(x) == get(f))
                rotate(f);
            else
                rotate(x);
        }
        rotate(x);
    }
    update(x);
}
int kth(int k, int u)
{
    if (k == t[t[u].ls].size + 1)
        return u;
    if (k <= t[t[u].ls].size)
        return kth(k, t[u].ls);
    if (k >= t[t[u].ls].size + 1)
        return kth(k - t[t[u].ls].size - 1, t[u].rs);
    return 0;
}
void Insert(int l, int len)
{
    int x = kth(l, root), y = kth(l + 1, root);
    splay(x, 0);
    splay(y, x);
    t[y].ls = build(1, len, y);
    update(y);
    update(x);
}
void del(int l, int r)
{
    int x = kth(l, root), y = kth(r + 1, root);
    splay(x, 0);
    splay(y, x);
    t[y].ls = 0;
    update(y);
    update(x);
}
void inorder(int u)
{
    if (u == 0)
        return;
    inorder(t[u].ls);
    cout << t[u].val;
    inorder(t[u].rs);
}
int main()
{
    t[1].size = 2, t[1].ls = 2;
    t[2].size = 1, t[2].fa = 1;
    root = 1, cnt = 2;
    int pos = 1;
    int n;
    cin >> n;
    while (n--)
    {
        int len;
        char opt[10];
        cin >> opt;
        if (opt[0] == 'I')
        {
            cin >> len;
            for (int i = 1; i <= len; i++)
            {
                char ch = getchar();
                while (ch < 32 || ch > 126)
                    ch = getchar();
                str[i] = ch;
            }
            Insert(pos, len);
        }
        if (opt[0] == 'D')
        {
            cin >> len;
            del(pos, pos + len);
        }
        if (opt[0] == 'G')
        {
            cin >> len;
            int x = kth(pos, root), y = kth(pos + len + 1, root);
            splay(x, 0);
            splay(y, x);
            inorder(t[y].ls);
            cout << endl;
        }
        if (opt[0] == 'M')
        {
            cin >> len;
            pos = len + 1;
        }
        if (opt[0] == 'P')
            pos--;
        if (opt[0] == 'N')
            pos++;
    }
    return 0;
}