砍竹子
2024-12-7 蓝桥杯每日一题 砍竹子 STL 贪心
题目大意
这天, 小明在砍竹子, 他面前有 nn 棵竹子排成一排, 一开始第 ii 棵竹子的 高度为 h i h_i hi. 他觉得一棵一棵砍太慢了, 决定使用魔法来砍竹子。魔法可以对连续的一 段相同高度的竹子使用, 假设这一段竹子的高度为 HH, 那么用一次魔法可以 把这一段竹子的高度都变为 [ ⌊ H 2 ⌋ + 1 ] \begin{bmatrix}\sqrt{\lfloor\frac{H}{2}\rfloor+1}\end{bmatrix} [⌊2H⌋+1 ], 其中 [ x ] \begin{bmatrix}x\end{bmatrix} [x] 表示对 x 向下取整。小明想 知道他最少使用多少次魔法可让所有的竹子的高度都变为 1 。
解题思路
这个题使用到了 STL 的技巧,有些不好想,咱们一步一步分析。
当前值改变的次数是否要加,取决于与它相邻的元素是否相等,这时候我们只看前面相邻的元素。。
当相邻元素减小到同一个值的时候,只需要计算一次即可,这一次怎么算,就是这些相邻相同的所有元素的对头那个来算,其他的都不算。
可以通过模拟每一个数的一个变化历程,然后对比前后的数据变化发现那些数是可以变化的。
举例:
cpp7 6 2 4 1 2 7 2 1 2 6 2 1 1 2 1 0 4 1 1 1 0 2 1 1
根据例子可以观察到每一个数的更新它所贡献的值只有与前一个数的变化历程不同的数的数量,那么就可以通过两个set集合来进行比较。
Accepted
cpp
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int n;
cin>>n;
ll res = 0;
set<ll> pri;
for(int i = 1;i <= n;i++) {
ll t;
cin>>t;
set<ll> pre;
while(t > 1) {
pre.insert(t);
if(!pri.count(t)) {
res++;
}
t = sqrtl(t/2+1);
}
pri = pre;
}
cout<<res<<endl;
return 0;
}
思考
这道题还是很难想出来的,必须通过模拟来观察规律求解!!!
备注
想要一起备赛的小伙伴可以私信加我的联系方式!