(多校)AVL 树
遍历贪心应该很好想
有一点需要注意
在判断一个点父亲的右子树时
需要考虑点的最深深度
以此来保证左子树的限制条件
我们开两个数组分别记录该点的最深深度和限制深度
在遍历时根据子树的深度信息更新限制深度
\(check\) 时需要考虑记录的限制深度
Code
#include <bits/stdc++.h>
#define re register
#define db double
#define int long long
// #define ll long long
#define pir make_pair
using namespace std;
const int N=2e6+10;
const int maxn=6E5+10;
const int INF=1e18+10;
// const int mol=998244353;
inline int read(){
int x=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9') w=(ch=='-')?-1:1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*w;
}
int n,k,root,cnt,fa[maxn],bin[maxn],lims[maxn],maxdep[maxn];
struct TREE { int l,r; } tre[maxn]; bool vis[maxn];
int dep[maxn],ds[maxn];
inline void dfs(int now) {
if(!now) return ;
dep[now]=ds[now]=dep[fa[now]]+1;
dfs(tre[now].l); dfs(tre[now].r);
ds[now]=max(ds[now],max(ds[tre[now].l],ds[tre[now].r]));
}
inline bool check(int now) {
int num=1,x=now,ls=max(maxdep[now],dep[now]);
int ks=0;
while(now) {
ls=max(ls,maxdep[now]);
if(now<fa[now]&&!vis[tre[fa[now]].r]) {
if(tre[fa[now]].r) num+=bin[max(ls-1,lims[tre[fa[now]].r])-dep[fa[now]]];
}
now=fa[now];
}
if(num<=k) {
now=x,ls=max(maxdep[now],dep[now]); maxdep[now]=ls;
vis[now]=1; k--;
while(now) {
if(now<fa[now]&&!vis[tre[fa[now]].r]) {
if(tre[now].r) lims[tre[fa[now]].r]=max(lims[tre[fa[now]].r],maxdep[now]-1);
}
maxdep[fa[now]]=max(maxdep[now],maxdep[fa[now]]);
now=fa[now];
}
}
return num<=k;
}
inline void slove(int now) {
if(!check(now)) return;
if(tre[now].l&&tre[now].r) {
if(ds[tre[now].l]>=lims[now]) {
lims[tre[now].l]=max(lims[tre[now].l],lims[now]);
lims[tre[now].r]=max(lims[tre[now].r],lims[now]-1);
} else {
lims[tre[now].l]=max(lims[tre[now].l],lims[now]-1);
lims[tre[now].r]=max(lims[tre[now].r],lims[now]);
}
slove(tre[now].l); slove(tre[now].r);
} else {
if(tre[now].l) {
lims[tre[now].l]=max(lims[tre[now].l],lims[now]);
slove(tre[now].l);
}
if(tre[now].r) {
lims[tre[now].r]=max(lims[tre[now].r],lims[now]);
slove(tre[now].r);
}
}
}
signed main(void) {
freopen("avl.in","r",stdin);
freopen("avl.out","w",stdout);
n=read(); k=read();
for(re int i=1;i<=n;i++) {
fa[i]=read(); if(fa[i]==-1) { root=i; continue; }
if(i<fa[i]) tre[fa[i]].l=i; else tre[fa[i]].r=i;
} fa[root]=0;
bin[1]=1; for(re int i=2;i;i++) { bin[i]=bin[i-1]+bin[i-2]+1; if(bin[i]>=n) break; }
dfs(root); slove(root);
for(re int i=1;i<=n;i++) if(vis[i]) printf("1"); else printf("0");
puts("");
return 0;
}