[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>g2i−1,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<g2i−1,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 n≤10;
对于 30 % 30\% 30%的数据, n ≤ 25 n ≤ 25 n≤25;
对于 70 % 70\% 70%的数据, n ≤ 1000 , 0 ≤ h i ≤ 1000 n ≤ 1000,0 ≤ h_i≤ 1000 n≤1000,0≤hi≤1000;
对于 100 % 100\% 100%的数据, 1 ≤ n ≤ 100 , 000 , 0 ≤ h i ≤ 1 , 000 , 000 1 ≤ n ≤ 100,000,0 ≤ h_i≤ 1,000,000 1≤n≤100,000,0≤hi≤1,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;
}