AVL 树

【问题描述】
AVL 树是经典的平衡二叉搜索树,他的定义如下:
• 平衡:对于任何一个点,他的左子树和右子树的高度差至多为 1。树的
高度定义为,根结点到子树内的点的最远距离。空子树的高度为-1。
• 二叉搜索树:每一个点都有一个相应的权值(两两不同),任何一个点
的权值都大于左子树中每个点的权值,且小于右子树中每个点的权值。
pks 得到了一棵 N 个节点,权值为 1~N 的 AVL 树,他觉得这棵树太大了,
于是他想要删掉一些节点使得最后剩下的树恰好有 K 个节点。如果 pks 删掉了
一个节点,那么以这个节点为根的整棵子树都会被删掉。最后剩下的树必须依
旧是一棵 AVL 树。

pks 希望,留下的 K 个节点的中序遍历的字典序最小。他希望你能帮他找到
这个方案,作为报答,他将会把自己的财富分一半给你。

// https://www.cnblogs.com/Oier-GGG/p/16047845.html

#include <bits/stdc++.h>

using namespace std;

#define int long long

int read() {
    int x;
    cin >> x;
    return x;
}

const int maxN = 5e5 + 7;

int n, k, R;

int heg[maxN], fa[maxN], lc[maxN], rc[maxN];
int f[maxN][25], g[maxN][25];

void upd(int x) {
    for (int t = 2; t <= heg[x]; t++) {
        int t1 = f[lc[x]][t - 1] + f[rc[x]][t - 1] + 1;
        int t2 = f[lc[x]][t - 1] + f[rc[x]][t - 2] + 1;
        int t3 = f[lc[x]][t - 2] + f[rc[x]][t - 1] + 1;
        f[x][t] = min({t1, t2, t3});
    }
    f[x][0] = 0;
    f[x][1] = 1;
}
void dfs(int x) {
    if (!x) return;
    dfs(lc[x]), dfs(rc[x]);
    heg[x] = max(heg[lc[x]], heg[rc[x]]) + 1;
    upd(x);
}

// int flag[maxN];
bool check(int x) {
    // if (flag[x]) return true;
    // flag[x]++;
    for (int i = 0; i <= heg[x]; i++)
        g[x][i] = f[x][i];
    f[x][0] = 1e18;
    while (x != R) {
        x = fa[x];
        for (int i = 0; i <= heg[x]; i++)
            g[x][i] = f[x][i];
        upd(x);
        f[x][0] = 1e9, f[x][1] = 1e9;
        // flag[x]++;
    }
    int minn = 1e9;
    for (int i = 1; i <= heg[R]; i++)
        minn = min(minn, f[R][i]);
    // cerr << minn << '\n';
    return minn <= k;
}
void C(int x) {
    // flag[x]--;
    for (int i = 0; i <= heg[x]; i++)
        f[x][i] = g[x][i];
    while (x != R) {
        x = fa[x];
        for (int i = 0; i <= heg[x]; i++)
            f[x][i] = g[x][i];
        // flag[x]--;
    }
}

signed main() {
    freopen("avl.in", "r", stdin);
    freopen("avl.out", "w", stdout);

    // freopen("sample.in", "r", stdin);
    // freopen("out.out", "w", stdout);

    ios::sync_with_stdio(false), cin.tie(nullptr);

    n = read(), k = read();
    for (int i = 1; i <= n; i++) {
        int f = read();
        if (f == -1)
            { R = i; continue; }
        fa[i] = f;
        if (i > f) rc[f] = i;
        else lc[f] = i;
    }

    memset(f, 0x3f, sizeof(f));
    f[0][0] = 0;
    dfs(R);

    for (int i = 1; i <= n; i++) {
        if (check(i))
            cout << 1;
        else
            cout << 0, C(i);
    }
}

posted @ 2024-10-14 17:53  ccxswl  阅读(17)  评论(1编辑  收藏  举报