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);
}
}