zhengjinyi
2024-11-17 10:38:00
将一棵满二叉树删为一棵指定的树,每次删除节点会将其所有儿子连到父亲节点上,求初始二叉树的最小高度。
记
用 bitset 可以做到 虽然没什么用。
考虑优化高精加的过程。\
因为我们只关心
(场上没发现进位
#include <bits/stdc++.h>
#define ll long long
#define pb emplace_back
#define R read()
using namespace std;
inline int read(){
int x=0;char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x;
}
const int inf=0x3f3f3f3f,N=1000005;
const ll INF=0x3f3f3f3f3f3f3f3f;
int T,n,f[N],p2[25];
vector<int> v[N];
void dfs(int x){
if(!v[x].size()){ f[x]=0; return; }
int mx=0;
vector<int> s;
for(int y:v[x]){
dfs(y);
s.pb(f[y]);
mx=max(mx,f[y]);
}
sort(s.begin(),s.end());
int w=0,lst=0,cnt=0;
for(int y:s){
if(y-lst>22&&w) w=1;
else w=ceil(1.0*w/p2[y-lst]);
w++;
lst=y;
}
while(w>1) w=ceil(w/2.0),cnt++;
f[x]=max(mx+1,s.back()+cnt);
}
int main(){
T=R;
p2[0]=1;
for(int i=1;i<25;i++) p2[i]=p2[i-1]<<1;
while(T--){
n=R;
for(int i=1;i<=n;i++) v[i].clear();
for(int i=2;i<=n;i++) v[R].pb(i);
dfs(1);
printf("%d\n",f[1]);
}
return 0;
}