砍竹子

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;
}
题目描述
有一个n×m 的棋盘,在某个点(x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入格式
输入只有一行四个整数,分别为 n,m,x,y。
输出格式
一个 n×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 −1−1)。
输入输出样例
输入 #1
3 3 1 1
输出 #1
0 3 2
3 -1 1
2 1 4
说明/提示
数据规模与约定
对于全部的测试点,保证 1≤x≤n≤400, 1≤y≤m≤400。

浙公网安备 33010602011771号