十三届蓝桥杯-砍竹子

文章介绍了一种使用优先队列和特殊存储技巧解决的砍竹问题,目标是找出最少魔法步骤使所有竹子高度相同。
摘要由CSDN通过智能技术生成

4409. 砍竹子

这天,小明在砍竹子,他面前有 n棵竹子排成一排,一开始第 i棵竹子的高度为 ℎi。

他觉得一棵一棵砍太慢了,决定使用魔法来砍竹子。

魔法可以对连续的一段相同高度的竹子使用,假设这一段竹子的高度为 H,那么使用一次魔法可以把这一段竹子的高度都变为\left \lfloor \sqrt{\left \lfloor \frac{H}{2} \right \rfloor+1} \right \rfloor,其中 表示对 x 向下取整。

小明想知道他最少使用多少次魔法可以让所有的竹子的高度都变为 1。

输入格式

第一行为一个正整数 n,表示竹子的棵数。

第二行共 n个空格分开的正整数 ℎi,表示每棵竹子的高度。

输出格式

一个整数表示答案。

数据范围

对于 20%的数据,保证 1≤n≤1000,1≤hi≤10^6
对于 100%的数据,保证 1≤n≤2×105,1≤hi≤10^18

输入样例:
6
2 1 4 2 6 7
输出样例:
5
样例解释

其中一种方案:

  2 1 4 2 6 7
→ 2 1 4 2 6 2
→ 2 1 4 2 2 2
→ 2 1 1 2 2 2
→ 1 1 1 2 2 2
→ 1 1 1 1 1 1

共需要 5步完成。

分析:

1.思路:

(1)每次取最大

(2)若有连续最大值,一起处理

2.how:

(1)如何取最大:优先队列(默认大根堆)

(2)如何判断是否存在连续区间:维护元素在原数组的位置(pair<value,id>)

想法一:设置两个数组pre[i]、pos[i]表示i前的位置和i后的位置(处理方式和十四届某道题神似)

(十四届整数删除的思路~)

想法二(大佬的想法):将id倒着存

即for(i:0~n-1) pair<value,n-i>

原因:当树高一样时,即value相等,排在队列前面的树也一定是原数组前面的树;那么,判断是否连续时,只须判断此时id是否 == pos - 1

注意点:

sqrt()和sqrtl()的区别:本题的数据范围是long long,所以处理平方和时要用sqrtl(),或者手写一个平方和公式也可~

代码:

#include<iostream>
#include<queue>
#include<cmath>
using namespace std;

typedef long long ll;
typedef pair<long long,int> PII;

int main()
{
    priority_queue<PII> q;
    int n;
    cin >> n;
    for(int i = 0;i < n;i ++)
    {
        ll h;
        cin >> h;
        q.push({h,n-i});  //倒着存
    }
    ll pre = q.top().first;  //1.取队首
    int pos = q.top().second;
    int ans = pre > 1 ? 1 : 0;  //可能一开始树高都为1,特判一下
    q.pop();
    q.push({sqrtl(pre/2+1),pos});
    while(!q.empty())  //2.进循环
    {
        PII p = q.top();
        q.pop();
        if(p.first == 1) continue;  //3.树高为1,continue
        if(p.first != pre || (p.first == pre && p.second != pos-1)) ans ++;  //4.和前一棵树树高不相等 or 不连续
        
        //5.处理树高
        pre = p.first;
        pos = p.second;
        q.push({sqrtl(pre/2+1),pos});
    }
    cout << ans << endl;
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值