平衡树splay

防止以后复习时忘掉

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

struct Tree
{
    int ch[2], fa, val, size;
} tree[40001];
int n, X, root;
int tot, lef_root, rig_root;
long long ans;

bool check(int now)
{
    return tree[tree[now].fa].ch[1] == now;//左孩子表示为0,右孩子表示为1
}

void rotate(int now)
{ 
    int father = tree[now].fa;
    int grand = tree[father].fa;
    int k=check(now);
    int son = tree[now].ch[k^1];//相反
    //孩子连接到爷爷,父亲原来为左孩子则孩子为左孩子
    tree[now].fa=grand,tree[grand].ch[check(father)]=now;
    //前驱后继方向于孩子相反
    tree[son].fa=father,tree[father].ch[k]=son;
    tree[father].fa=now,tree[now].ch[k^1]=father;
}

void splay(int x, int target)
{ 
    while (tree[x].fa != target)
    {
        if (tree[tree[x].fa].fa != target)
        {
            if(check(x)==check(tree[x].fa))
                rotate(tree[x].fa);
            else 
                rotate(x);
        }
        rotate(x);
    }

    if (!target)
        root = x;
}

int find(int x)
{
    int now = root;
    while (now)
    {
        if (x == tree[now].val)
            break;
        if (x >= tree[now].val)
            now = tree[now].ch[1];
        else
            now = tree[now].ch[0];
    }
    if (now != root)
        splay(now, 0);
    return now;
}

void insert(int x)
{
    int now = root, last = 0;
    while (now)
    {
        last = now;
        tree[now].size++;
        if (x < tree[now].val)
            now = tree[now].ch[0];
        else
            now = tree[now].ch[1];
    }

    tot++;//新加一个节点
    tree[tot].fa = last;
    tree[tot].val = x;
    tree[tot].size = 1;
    if (x < tree[last].val)
        tree[last].ch[0] = tot;
    else
        tree[last].ch[1] = tot;

    splay(tot, 0);
}

void join(int small, int big)
{
    tree[small].fa = tree[big].fa = 0;
    int new_root = small;
    while (tree[new_root].ch[1])//找到左子树中最大的
        new_root = tree[new_root].ch[1];
    splay(new_root, 0);
    tree[new_root].ch[1] = big;
    tree[big].fa = new_root;
}

void delete_(int x)
{
    splay(x, 0);//删掉自己=把左子树+右子树
    if (!tree[x].ch[0] && tree[x].ch[1])
        tree[tree[x].ch[1]].fa = 0;
    else if (tree[x].ch[0] && !tree[x].ch[1])
        tree[tree[x].ch[0]].fa = 0;
    else
        join(tree[x].ch[0], tree[x].ch[1]);

    tree[x].ch[0] = tree[x].ch[1] = 0;
}

int get_rank(int x)//得到排名
{
    int now = find(x);
    return tree[tree[now].ch[0]].size + 1;//左边孩子都小于我,所以排名为左子树节点数量+1
}

void spilt(int x)//分开
{
    int no_root = find(x);//find后x为根节点
    lef_root = tree[no_root].ch[0];//分开
    rig_root = tree[no_root].ch[1];
    tree[no_root].ch[0] = tree[no_root].ch[1] = 0;
}

int pre(int x)
{ 
    int now = root;//此时x为根节点
    now = tree[now].ch[0];
    if (!now)
        return -1;
    while (tree[now].ch[1])//左子树最右边的点
    {
        now = tree[now].ch[1];
    }
    return tree[now].val;
}

int nxt(int x)
{ 
    int now = root;//此时x为根节点
    now = tree[now].ch[1];
    if (!now)
        return -1;
    while (tree[now].ch[0])
    {
        now = tree[now].ch[0];//右子树最左边的点
    }
    return tree[now].val;
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &X);

        insert(X);

        if (i == 1)
            ans += 1ll * X;
        else
        {
            int XX = pre(X), YY = nxt(X);
            if (XX == -1)
                ans += YY - tree[root].val;
            else if (YY == -1)
                ans += tree[root].val - XX;
            else
                ans += min(tree[root].val - XX, YY - tree[root].val);
        }
    }

    printf("%lld", ans);

    return 0;
}
posted @ 2025-05-26 18:44  流氓兔LMT  阅读(11)  评论(0)    收藏  举报