[NOIP2013 提高组] 花匠

[NOIP2013 提高组] 花匠

题目描述

花匠栋栋种了一排花,每株花都有自己的高度。花儿越长越大,也越来越挤。栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致。

具体而言,栋栋的花的高度可以看成一列整数 h 1 , h 2 , . . . , h n h_1,h_2,...,h_n h1,h2,...,hn。设当一部分花被移走后,剩下的花的高度依次为 g 1 , g 2 , . . . , g m g_1,g_2,...,g_m g1,g2,...,gm,则栋栋希望下面两个条件中至少有一个满足:

条件 A A A:对于所有 g 2 i > g 2 i − 1 , g 2 i > g 2 i + 1 g_{2i}>g_{2i-1},g_{2i}>g_{2i+1} g2i>g2i1,g2i>g2i+1

条件 B B B:对于所有 g 2 i < g 2 i − 1 , g 2 i < g 2 i + 1 g_{2i}<g_{2i-1},g_{2i}<g_{2i+1} g2i<g2i1,g2i<g2i+1

注意上面两个条件在 m = 1 m=1 m=1时同时满足,当 m > 1 m > 1 m>1时最多有一个能满足。

请问,栋栋最多能将多少株花留在原地。

输入格式

第一行包含一个整数 n n n,表示开始时花的株数。

第二行包含 n n n个整数,依次为 h 1 , h 2 , . . . , h n h_1,h_2,...,h_n h1,h2,...,hn,表示每株花的高度。

输出格式

一个整数 m m m,表示最多能留在原地的花的株数。

样例 #1

样例输入 #1

5
5 3 2 1 2

样例输出 #1

3

提示

【输入输出样例说明】

有多种方法可以正好保留 3 3 3 株花,例如,留下第 1 1 1 4 4 4 5 5 5 株,高度分别为 5 5 5 1 1 1 2 2 2,满足条件 B。

【数据范围】

对于 20 % 20\% 20%的数据, n ≤ 10 n ≤ 10 n10

对于 30 % 30\% 30%的数据, n ≤ 25 n ≤ 25 n25

对于 70 % 70\% 70%的数据, n ≤ 1000 , 0 ≤ h i ≤ 1000 n ≤ 1000,0 ≤ h_i≤ 1000 n1000,0hi1000

对于 100 % 100\% 100%的数据, 1 ≤ n ≤ 100 , 000 , 0 ≤ h i ≤ 1 , 000 , 000 1 ≤ n ≤ 100,000,0 ≤ h_i≤ 1,000,000 1n100,000,0hi1,000,000,所有的$h_i $随机生成,所有随机数服从某区间内的均匀分布。

通过模拟题意可得,这道题的答案与波峰或波谷的个数有关,这是最重要的。

求波峰或波谷个数的套路

#include<bits/stdc++.h>
using namespace std;
int n,h[1000005],ans=1;bool con;
int main()
{
    cin>>n;for(int i=1;i<=n;i++) cin>>h[i];
    if(h[2]>=h[1]) con=1;
    for(int i=1;i<=n;i++)
    {
        if(con==0&&i==n) {ans++;break;}
        if(con==1) if(h[i+1]<h[i]){ans++;con=0;continue;}
        if(con==0) if(h[i+1]>h[i]) {ans++;con=1;continue;}
    }
    cout<<ans; 
}

这道题我们可以联想到最长不下降子序列,因为两者都是求一个满足条件的最长的序列。

本人在想这道题的时候想用区间DP,但现在想想还是没有仔细模拟样例,如果是区间DP的话,f[i +1] [j]肯定包含在f[i] [j]里面中,只有j需要变,不需要区间。在比赛过程中,我知道自己打错了,但也发现过来波峰即时波谷,过了波谷即是波峰,所以A,B是掺杂一体的,而不是互斥的。

设f[i] [0 / 1],i表示右端点,0,1表示数据变化的趋势。

if(a[i] > a[i - 1])
f[i][1] = f[i - 1][0] + 1.
else f[i][0] = f[i - 1][0]
if(a[i] < a[i - 1])
f[i][0] = f[i - 1][1] + 1
else f[i][0] = f[i - 1][0]
if(a[i] > a[i - 1])
{
	f[i][1] = max(f[i - 1][1],f[i - 1][0] + 1);
	f[i][0] = f[i - 1][0];
}else{
	f[i][0] = max(f[i - 1][0],f[i - 1][1] + 1);
	f[i][1] = f[i - 1][1];
}
#这里是错误的,因为没有包含相等的情况#  

正解:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n,a[N],ans;
int f[N][2];

int main()
{
	scanf("%d",&n);
	
	for(int i = 1;i <= n;i ++)
		scanf("%d",&a[i]);
	
	f[1][0] = f[1][1] = 1;
	for(int i = 2;i <= n;i ++)
	{
		if(a[i] > a[i - 1])
			f[i][1] = max(f[i - 1][1],f[i - 1][0] + 1);
		else 	f[i][1] = f[i - 1][1];
		if(a[i] < a[i - 1])
			f[i][0] = max(f[i - 1][0],f[i - 1][1] + 1);
		else 	f[i][0] = f[i - 1][0];
		
	}
	
	printf("%d",max(f[n][0],f[n][1]));
	
	return 0;
}
posted @ 2022-09-24 21:16  zyc_xianyu  阅读(73)  评论(0编辑  收藏  举报