【2025年莆田市第五期C++专项第三轮选拔真题(小学组)】发喜糖
发喜糖
一场隆重的巨人族婚礼正在进行。
喜庆的节日自然少不了发喜糖环节。
现在有n
个巨人站成一排等着发喜糖,每个巨人都有一个身高值(整数)。
身材高的巨人总是有优越感,所以发的喜糖不能比旁边矮的巨人少。
于是主人便定了以下规则发喜糖:
- 每个巨人至少能分到
1
个糖果。 - 相邻两个巨人身高更高的会获得更多的果糖。
按以上规则给每个巨人发果糖,请统计下 最少的果糖数目 。
输入
输入有两行。
第一行有一个整数n
.
第二行有n
个整数
h
i
h_i
hi,分别表示n
个巨人的身高
输出
输出一个整数,表示最少得果糖数目。
输入样例一:
3
1 0 2
输出样例一:
5
输入样例二:
3
1 2 2
输出样例二:
3
样例一解释:分发2、1、2 颗
样例二解释:分发 1、2、1 颗
数据范围:
10 % 10 \% 10%的数据: 1 ≤ n ≤ 100 1 \leq n \leq 100 1≤n≤100且身高具有单调性(递增或者递减)
40 % 40 \% 40%的数据: 1 ≤ n ≤ 10000 , h i ≤ 10000 1 \leq n \leq 10000 ,h_i \leq 10000 1≤n≤10000,hi≤10000
100 % 100 \% 100%的数据: 1 ≤ n ≤ 500000 , h i ≤ 1000000 1 \leq n \leq 500000 , h_i \leq 1000000 1≤n≤500000,hi≤1000000
问题理解
这个问题要求我们按照特定规则给一排巨人分发喜糖。规则如下:
- 每个巨人至少分到1个糖果
- 相邻两个巨人中,身高更高的必须获得更多的糖果
我们需要找到满足这些条件的最少糖果总数。
解题思路
这个问题可以通过两次遍历数组来解决:
- 从左到右遍历:确保每个巨人比左边邻居高时,糖果数也比左边多
- 从右到左遍历:确保每个巨人比右边邻居高时,糖果数也比右边多
这种方法类似于经典的"糖果分配"问题,通过两次遍历可以保证所有相邻关系都满足条件。
代码实现
#include <iostream>
using namespace std;
typedef long long ll;
const int MAX_N = 5e5 + 10;
int n; // 巨人数量
int heights[MAX_N]; // 每个巨人的身高
int candies[MAX_N]; // 每个巨人分到的糖果数
ll totalCandies = 0; // 糖果总数
int main() {
// 输入巨人数量
cin >> n;
// 输入每个巨人的身高
for (int i = 0; i < n; ++i) {
cin >> heights[i];
}
// 初始化每个巨人至少分到1个糖果
for (int i = 0; i < n; ++i) {
candies[i] = 1;
}
// 从左到右遍历,确保右边比左边高的巨人分到更多糖果
for (int i = 1; i < n; ++i) {
if (heights[i] > heights[i - 1]) {
if (candies[i] <= candies[i - 1]) {
candies[i] = candies[i - 1] + 1;
}
}
}
// 从右到左遍历,确保左边比右边高的巨人分到更多糖果
for (int i = n - 2; i >= 0; --i) {
if (heights[i] > heights[i + 1]) {
if (candies[i] <= candies[i + 1]) {
candies[i] = candies[i + 1] + 1;
}
}
}
// 计算糖果总数
for (int i = 0; i < n; ++i) {
totalCandies += candies[i];
}
// 输出结果
cout << totalCandies << '\n';
return 0;
}
复杂度分析
- 时间复杂度:O(n),因为我们只进行了两次线性遍历
- 空间复杂度:O(n),用于存储身高和糖果数量数组