0
点赞
收藏
分享

微信扫一扫

校OJ:这爬山是一件美事

灵魂跑者 2022-03-26 阅读 163

这爬山多是一件美事

题目描述
  话说这天老冯爬山给大伙送鸡汤。爬山的过程中,山顶和山谷的连接都会使得山路高低起伏,作为一个催逝员的老冯当然想着让山顶或者山谷如何变少,这走平路多是一件美事啊!于是老冯把这连绵起伏的山脉看作一个长度为 n n n的整数数列 a n a_n an。对于任意一个 i ( 1 < i < n ) i(1<i<n) i(1<i<n),当 a i > a i − 1 a_i>a_{i-1} ai>ai1 a i > a i + 1 a_i>a_{i+1} ai>ai+1时,老冯认为 i i i是一个山峰。同理当 a i < a i − 1 a_i<a_{i-1} ai<ai1 a i < a i + 1 a_i<a_{i+1} ai<ai+1,老冯认为 i i i是个山谷。现在老冯要启动他的山峰改造计划了,假设老冯最多可以修改一次序列 a n a_n an,每次修改操作使得序列 a n a_n an中的一个整数变为另一个整数。那么最后序列中山峰和山谷的数量之和的最小值是多少?
输入
每一行包括一个整数 T T T,表示测试数据的组数
每一组测试数据第一行包含一个正整数 n ( 1 ≤ n ≤ 3 × 1 0 5 ) n(1\le n\le 3\times10^5) n(1n3×105),表示山脉长度
每一组测试数据第二行包含 n n n个整数 a 1 , a 2 , a 3 , . . . , a n ( 0 ≤ a i ≤ 1 0 9 ) a_1,a_2,a_3,...,a_n(0\le a_i\le10^9) a1,a2,a3,...,an(0ai109),表示山脉序列
保证所有测试数据的 n n n之和小于等于 3 × 1 0 5 3\times10^5 3×105
输出
对于每组测试数据,输出包括一行一个整数,表示山峰和山谷数量之和的最小值
样例输入

样例输出

提示
对于第一组测试数据 1 5 3 来说, 将 a 2 a_2 a2修改为1或3即可,此时没有山峰或山谷
对于第二组测试数据 2 2 2 2 2 , 不需要修改
对于第三组测试数据, 一种修改方式是将 a 3 a_3 a3修改为6

AC代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 10;
int T, n;
int num[maxn];
int ans;
bool check(int x) {
	if(x == 1 || x == n) return false;
	else if((num[x+1] > num[x] && num[x-1] > num[x])	//山谷 
		|| (num[x+1] < num[x] && num[x-1] < num[x]))	  //山峰 
		return true;
	else return false;
}
int main() {
	scanf("%d", &T);
	while(T--) {
		scanf("%d", &n);
		for(int i = 1; i <= n; i++) {
			scanf("%d", &num[i]);
		}
		
		int sum = 0, max_num = 0;
		for(int i = 1; i <= n; i++) {
			if(check(i)) sum++;
 		}
 		ans = sum;
 		for(int i = 2; i < n; i++) {
 			int pos = num[i];
 			int ans1 = check(i) + check(i-1) + check(i+1);
 			num[i] = num[i-1];
 			int ans2 = check(i) + check(i-1) + check(i+1);
 			num[i] = num[i+1];
 			int ans3 = check(i) + check(i-1) + check(i+1);
 			num[i] = pos;
 			max_num = max(max_num, max(ans1-ans2, ans1-ans3));
		}
		printf("%d\n", max(ans-max_num, 0));
	}
	return 0;
}

代码分析

假设下标是 i i i一个山峰或山谷, 则只需将下表 i i i的值尽可能修改为其左边或右边的值或者不进行修改。由于每次修改只可能影响三个位置的状态,只需判断相邻及其位置剩余的峰谷的数量,最后求最小值。
请添加图片描述
请添加图片描述
max_num其实是修改后相对于修改前峰谷的削减量,算出削减量的最大值再用总峰谷数减去最大值便可以得到最小值。

举报

相关推荐

0 条评论