Codeforces Round #695 (Div. 2)-B. Hills And Valleys

B. Hills And Valleys

数学 暴力

  • 题设:T个样例下,每个样例输入n,和长度为n的序列a【i】各位的值。
    定义:当j (2 ≤ j ≤ n−1)时,若 a[j] > a[j+1] 且 a[j] > a[j−1] 则称这点位波峰,若 a[j] < a[j+1] 且 a[j] < a[j−1] 则称这点为波谷。
    现可对序列中任意一个位置的值修改。问改动一次后,整个序列中波峰和波谷的总数,最少是多少。
  • 思路: 计算改动前的峰谷总数是多少后,单个for循环加特判可解决此问题。

简单的“心电图”,操作无非就是两种:
要么把a【i】变成 a【i+1】,要么把a【i+1】变成 a【i】。
但是在这里,A边和E边是否存在,会影响到改变后是否会出现新的峰/谷,此时B,C,D的大小又有抵消这个影响的可能。
此题的坑点就是:消去两个峰/谷的情况只有四种。
要解决的就是六点五边之间的各种关系,五条边分别命名为A,B,C,D,E。基本图示如下。
Codeforces Round #695 (Div. 2)-B. Hills And Valleys_第1张图片

  1. 连着三个点都是峰/谷的时候,无论五条边的长度如何,此时都可以对中间点处理消去三个峰/谷,这也是最好的情况。
    Codeforces Round #695 (Div. 2)-B. Hills And Valleys_第2张图片

  2. B >= C,此时可以消去两个峰/谷。Codeforces Round #695 (Div. 2)-B. Hills And Valleys_第3张图片

  3. D >= C,此时也可消去两个峰/谷。Codeforces Round #695 (Div. 2)-B. Hills And Valleys_第4张图片

  4. A == 0 或 E == 0的情况,可消去两个峰/谷。Codeforces Round #695 (Div. 2)-B. Hills And Valleys_第5张图片

  5. 构不成六点五边的时候,即在序列的两端时,i ==2 或者 i ==n-2。可消去两个峰/谷。(两种情况都可用此图表示)Codeforces Round #695 (Div. 2)-B. Hills And Valleys_第6张图片

注意,仅仅是两个峰/谷相邻,但是2,3,4,5四个条件均不满足时,即此时B 简单画图示意即可明白文章开头说的,什么是“A和E的影响”,什么又是“B,C,D可抵消这种影响”。
AC代码:

#include
#define ll long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
priority_queue <int,vector<int>,less<int> > QM;
const int INF= 0x3f3f3f3f;
const int maxn= 3e5+5;

int a[maxn],vis[maxn];
void solve()
{
     
	int n;cin>>n;
	for(int i=1;i<=n;i++)	cin>>a[i];
	for(int i=0;i<=n+1;i++)	vis[i] =0;
	
	int ans=0,cnt=0;
	for(int i=2;i<=n-1;i++)
	{
     
		if(a[i]>a[i-1] && a[i]>a[i+1])	vis[i]=1,ans++;
		if(a[i]<a[i-1] && a[i]<a[i+1])	vis[i]=1,ans++;
	}
	if(ans!=0)	cnt=1;
	for(int i=2;i<=n-1;i++)
	{
     
		if(vis[i])
		{
     
			if(vis[i] && vis[i-1] && vis[i+1])
			{
     
				cnt=3;
				break;
			}
			if(vis[i+1] && (i==2 || i==n-2))
				cnt = 2;
			if(vis[i+1] && abs(a[i-1]-a[i])>=abs(a[i+1]-a[i]))
				cnt = 2;
			if(vis[i+1] && abs(a[i+2]-a[i+1])>=abs(a[i]-a[i+1]))
				cnt = 2;
			if(vis[i+1] && (a[i-2]==a[i-1] || a[i+2]==a[i+3]))
				cnt = 2;
		}
	}
	cout<<ans-cnt<<endl;
}
int main()
{
     
	IOS;
	int t;cin>>t;
	while(t--){
      solve(); }
	return 0;
}

你可能感兴趣的:(codeforces,acm竞赛)