(多校)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;
}
posted @ 2021-10-08 19:33  zJx-Lm  阅读(31)  评论(0编辑  收藏  举报