砍竹子(蓝桥杯 2022 省赛 B 组 J 题)

砍竹子

AC代码:

#include<iostream>
#include<queue>
#include<math.h>
using namespace std;
long long res;
struct node
{
	long long val,l, r;
};

bool operator <(node a, node b)
{
	return a.val == b.val ? a.l < b.l : a.val < b.val;//定义调堆的规则,如果值相等的情况下,优先考虑左区间大的
}

int main(void)
{
	long long n, k;
	priority_queue<node>p;//定义一个node类型的堆
	scanf("%lld", &n);
	for (int i = 1; i <= n; i++)
	{
		scanf("%lld", &k);
		p.push({ k,i,i });
	}
	while (p.top().val != 1)
	{
		node t = p.top();//取出当前的堆顶元素(最大值)
		p.pop();//先将最大值出堆,等砍掉之后还会将高度重新入堆
		node top;//用于等会记录堆中第二大的值
		while (!p.empty())
		{
			top = p.top();//堆中第二大的值
			if (t.val == top.val && t.l - 1 == top.r)//如果最大值和第二大的值相等,并且区间差只有1,就是相邻的竹子
			{
				p.pop();//一起砍掉,就是先pop掉第二大的,所有相等的且相邻的只用保留一个数就行了,当这个数被砍为1的时候相当于所有相邻的都被砍为1了
				t.l = top.l;//相当于合并区间了
			}
			else
			{
				break;//如果没有可以一并砍掉的就直接跳出循环
			}
		}
		int val = sqrtl(t.val / 2 + 1);//计算
		p.push({ val,t.l,t.r });//将砍了之后的高度加入堆中
		res++;//砍的次数+1
	}
	printf("%lld", res);
	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值