开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第35天,点击查看活动详情
[蓝桥杯 2022 省 B] 砍竹子
题目描述
这天,小明在砍竹子,他面前有 棵竹子排成一排,一开始第 棵竹子的高度为 .
他觉得一棵一棵砍太慢了,决定使用魔法来砍竹子。魔法可以对连续的一段相同高度的竹子使用,假设这一段竹子的高度为 ,那么使用一次魔法可以把这一段竹子的高度都变为 , 其中 表示对 向下取整。小明想知道他最少使用多少次魔法可以让所有的竹子的高度都变为 。
输入格式
第一行为一个正整数 ,表示竹子的棵数。
第二行共 个空格分开的正整数 ,表示每棵竹子的高度。
输出格式
一个整数表示答案。
样例 #1
样例输入 #1
6
2 1 4 2 6 7
样例输出 #1
5
提示
【样例说明】
其中一种方案:
共需要 5 步完成
【评测用例规模与约定】
对于 的数据,保证 。
对于 的数据,保证 。
蓝桥杯 2022 省赛 B 组 J 题。
分析
这题是一个贪心题,暴力肯定过不去,用堆的话,时间复杂度比较吃紧,我们想到把一根竹子变成1最多只要操作6次,所以可以把每一根竹子的每一段都存下来,然后看看相邻一段有没有相等的有,次数就--就ok了
代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int N=2e5+10;
const int M=10;
#define ll long long
ll a[N];
ll f[N][M];
ll stk[N];
int main(){
int n;
cin>>n;
ll res=0;
int maxn=-1;
for(int i=1;i<=n;i++){
ll x;
cin>>x;
int top=0;
while(x>1){
stk[++top]=x;
x=sqrtl(x/2+1);
}
res+=top;
maxn=max(maxn,top);
for(int j=1,k=top;k;j++,k--){
f[i][j]=stk[k];
}
}
for(int i=2;i<=n;i++){
for(int j=1;j<=maxn;j++){
if(f[i][j] && f[i][j]==f[i-1][j]){
res--;
}
}
}
cout<<res<<endl;
return 0;
}
希望能帮助到大家,qaq!