找了老半天错误。。
高度为i的平衡树至少要有f(i)=f(i-1)+f(i-2)+1个结点
从小到达枚举i,如果i被选中,那么其所有祖先p也必被选中
考虑i能否加入:如果i在祖先p的左子树里,p的左子树高度更新,连带更新右子树必须要有的高度
如果i在组先p的右子树里,更新右子树高度,只要右子树高度<=左子树高度+1即可
/* 高度为i的平衡树至少要有f(i)=f(i-1)+f(i-2)+1个结点 从小到达枚举i,如果i被选中,那么其所有祖先p也必被选中 考虑i能否加入:如果i在祖先p的左子树里,p的左子树高度更新,连带更新右子树必须要有的高度 如果i在组先p的右子树里,更新右子树高度,只要右子树高度<=左子树高度+1即可 */ #include<bits/stdc++.h> using namespace std; #define N 600005 int ans[N],k,n,mi[N],ls[N],rs[N],fa[N],dl[N],d[N]; void dfs(int u){ if(ls[u]){ d[ls[u]]=d[u]+1; dfs(ls[u]); } if(rs[u]){ d[rs[u]]=d[u]+1; dfs(rs[u]); } } int main(){ mi[1]=1;mi[2]=2; for(int i=3;i<=3000;i++) mi[i]=mi[i-1]+mi[i-2]+1; cin>>n>>k; for(int i=1;i<=n;i++){ cin>>fa[i]; if(fa[i]!=-1){ if(i<fa[i])ls[fa[i]]=i; else rs[fa[i]]=i; } } int root; for(int i=1;i<=n;i++)if(fa[i]==-1)root=i; dfs(root); for(int i=1;i<=n;i++)if(!ans[i]){ int pre=fa[i],now=i,tot=k; while(pre!=-1){ if(!ans[pre])tot--;//祖先没被选过 if(now==ls[pre]){//now是pre左子树 int t=d[i]-d[pre]; if(dl[pre]<t) tot-=mi[t-1]; else tot-=mi[dl[pre]-1]; }else{//now是pre右子树 if(!ans[pre]){tot=-1;break;} int t=d[i]-d[pre]; if(t>dl[pre]+1){tot=-1;break;} } now=pre;pre=fa[now]; } if(tot>=1){ ans[i]=1;k--; int pre=fa[i],now=i; while(pre!=-1){ if(!ans[pre])ans[pre]=1,k--; if(now==ls[pre]){ int t=d[i]-d[pre]; if(dl[pre]<t){ dl[pre]=t; } } now=pre;pre=fa[pre]; } }else { ans[i]=0; } } for(int i=1;i<=n;i++)cout<<ans[i]; }