(多校)AVL 樹
阿新 • • 發佈:2021-10-08
遍歷貪心應該很好想
有一點需要注意
在判斷一個點父親的右子樹時
需要考慮點的最深深度
以此來保證左子樹的限制條件
我們開兩個陣列分別記錄該點的最深深度和限制深度
在遍歷時根據子樹的深度資訊更新限制深度
\(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; }