将竹子不论具体高度,而是利用每个高度在计算一次后减少一层,这样每个竹子都可以分为不同层,利用f(i,j)数组存放第i个竹子,在计算j次后的高度是多少(j=0为最后一次砍到1的高度),必须用一个栈存放高度,在将砍伐后的高度赋值给f(i,j),因为要保证从按照由高度从小到达的顺序j=0时是所有竹子最后一次砍伐,也就是j=0为同一层,如果不利用栈,那么j=0时所有竹子未必保证在同一层高度。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+10,M=10;
int n,m;
ll f[N][M];
int main(){
ll s[N];//栈存放每一层竹子高度
cin>>n;
int res=0; //计算最坏所需要砍多少下
for(int i=0;i<n;i++){
ll x;
cin>>x;
int top=0;
while(x>1)s[++top]=x,x=sqrtl(x/2+1);
res+=top;
m=max(m,top);//最多砍多少下
for(int j=0,k=top;k;j++,k--)f[i][j]=s[k];//第i棵竹子,第j层高度(由小到大)
}
for(int i=0;i<m;i++){//从下层砍到上层
for(int j=1;j<n;j++){
if(f[j][i]&&f[j][i]==f[j-1][i])res--;//可以一起砍掉
}
}
cout<<res<<endl;
return 0;
}