P6364 [传智杯 #2 初赛] 1024 程序员节发橙子

80 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情

[传智杯 #2 初赛] 1024 程序员节发橙子

题目描述

每年的 1024 程序员节日,黑马程序员都会举办大型的庆祝活动。今年的程序员节也不例外,每个班级的同学都发了橙子。

班级里有 nn 名同学从前到后排成一排,且已经得知了这些同学的成绩,其中第 ii 名同学的成绩是 aia_i。班主任想根据同学们上个阶段的考试成绩来评定发橙子的数量。为了激励成绩优秀同学,发橙子时需要满足如下要求:

  • 相邻同学中成绩好的同学的橙子必须更多。若相邻的同学成绩一样,则它们分到的数量必须平等。
  • 每个同学至少分配一个橙子

由于预算有限,班主任希望在符合要求的情况下发出尽可能少的橙子。请问,至少需要准备多少橙子呢?

输入格式

第一行是一个整数 nn,表示学生数量。

接下来一行有 nn 个整数,第 ii 个整数 aia_i,表示第 ii 个同学的成绩。

输出格式

输出答案,也就是需要最少准备多少个橙子。

样例 #1

样例输入 #1

5
3 4 5 4 3

样例输出 #1

9

提示

样例 1 解释

每位同学拿到的橙子的数量分别是 1,2,3,2,11,2,3,2,1,所以至少需要准备 99 个。

数据规模与约定

对于全部的测试点,保证 1n1061 \leq n \leq 10^60ai1090 \leq a_i \leq 10^9

解题思路

  • 仔细查看题目你会发现,这道题有点像一个波浪,也就是一下子递增一下子递减,我们只要记录它正向递增和逆向递减所造成的橙子变化即可
  • 正向看
    • 如果前一项比后一项大,那么前一项的橘子数较后一项加一(相当于前缀和的思路)
    • 如果前一项和后一项相等,那么前一项的橘子树对于后一项橘子数
  • 逆向看
    • 如果后一项比前一项大,那么后一项有一个判断
      • 即后一项是不是正向的驼峰,如果是的话得判断是前一项加一大还是后一项大
    • 总结下来就是一个max来判断
    • 如果后一项和前一项一样大,那么后一项等于前一项
  • 累加输出

代码展示

#include<iostream>
using namespace std;

const int N = 1e6 + 10;
int a[N], w[N];
long long res;

int main()
{
	int n;
	cin >> n;
	//存储及初始化
	for (int i = 1; i <= n; i++)cin >> a[i], w[i] = 1;

	//正向标记
	for (int i = 2; i <= n; i++) {
		if (a[i] > a[i - 1])w[i] = w[i - 1] + 1;
		if (a[i] == a[i - 1])w[i] = w[i - 1];
	}

	//逆向标记
	for (int i = n; i >= 2; i--) {
		if (a[i - 1] > a[i])w[i - 1] = max(w[i - 1], w[i] + 1);
		if (a[i - 1] == a[i])w[i - 1] = w[i];
	}

	//求和
	for (int i = 1; i <= n; i++)res += w[i];
	cout << res;
	return 0;
}

PS:这是一道有点意思的题目~