Noip 2013 Day2 T2 花匠(flower)
Noip 2013 Day2 T2 花匠(flower)
【问题描述】
花匠栋栋种了一排花,每株花都有自己的高度。花儿越长越大,也越来越挤。栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致。
具体而言,栋栋的花的高度可以看成一列整数ℎ1, ℎ2, … , ℎn。设当一部分花被移走后,剩下的花的高度依次为𝑔1, 𝑔2, … , 𝑔m,则栋栋希望下面两个条件中至少有一个满足:
条件 A:对于所有的1 ≤ 𝑖 ≤𝑚2,有𝑔2𝑖> 𝑔2𝑖−1 , 同时对于所有的 1 ≤ 𝑖 <𝑚2,有𝑔2𝑖
> 𝑔2𝑖+1;
条件 B:对于所有的1 ≤ 𝑖 ≤𝑚2,有𝑔2𝑖< 𝑔2𝑖−1,同 时对于所有的1 ≤ 𝑖 <𝑚2
,有𝑔2𝑖< 𝑔2𝑖+1。
注意上面两个条件在� = 1时同时满足,当� > 1时最多有一个能满足。
请问,栋栋最多能将多少株花留在原地。
【输入】
输入文件为 flower .in。
输入的第一行包含一个整数n,表示开始时花的株数。
第二行包含n个整数,依次为ℎ1, ℎ2, … , ℎn,表示每株花的高度。
【输出】
输出文件为 flower .out。
输出一行,包含一个整数m,表示最多能留在原地的花的株数。
那么这道题做得时候困扰了我很就,我读了很久的题,一直以为是前半部分上升序列,后半部分下降序列,或者互换过来。后来,我写了一个动归,突然,我发现这道题,其实求的是一个波浪形的序列。
目说什么2i,2i-1,2i+1。搞得很难看懂
其实就是说一个数比前一个数小的同时比后一个数大,或者比前一个数大的同时比后一个数小,这样的波浪形序列是满足条件的。
/*
假设当前最优地取到了g[k],并且下一个是波峰,则对于下一个元素k+1:
若g[k]<g[k+1],说明符合题意,可以继续贪心下去。
若g[k]>g[k+1],说明之前若选择g[k+1],则可以取为波峰的情况就更多,于是我们就将最优序列中的g[k]替换成g[k+1]。
同时根据上述贪心,有以下推论:第一个元素是必须要取的。这也是一种很常见的贪心策略。
证明:如果不取第一个元素,就必须有取第k个元素,使得最后得到的解最优(假设下一个要去的元素下标为j)。假设从波谷开始,那么有g[k]<g[j]:
若g[1]≤g[j],则不必考虑从g[k]转移,因为[2,k]之间可能会产生更多转移;
若g[1]>g[j],那么我们就可以从波峰开始,最后结果必然是g[j]的最优解+1。
同理可证波峰开始的情况。
在缩进了所有相邻元素相同的情况下,不但一定要取最后一个数的贪心可以证明,而且最后的数据整体也就是大波浪形,于是我们在每一个大波浪的谷峰谷底取一下即可。
*/
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 #include <cstring> 6 #define INT_MAX_ 0x7fffffff 7 #define LONG_MAX_ 0x7fffffffffffffffll 8 #define pi acos(-1) 9 #define N 100010 10 #define M 1000010 11 using namespace std; 12 13 inline int read() 14 { 15 int data=0,w=1; 16 char ch=0; 17 while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar(); 18 if(ch=='-') w=-1,ch=getchar(); 19 while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar(); 20 return data*w; 21 } 22 23 inline void write(int x) 24 { 25 if(x<0) putchar('-'),x=-x; 26 if(x>9) write(x/10); 27 putchar(x%10+'0'); 28 } 29 30 int n,top,ans; 31 int hight[N]; 32 33 int main() 34 { 35 freopen("flower.in","r",stdin); 36 freopen("flower.out","w",stdout); 37 38 n = read(); 39 for(int i = 1; i <= n; i++) 40 { 41 hight[i] = read(); 42 } 43 for(int i = 1; i <= n; i++) //去重 44 { 45 if(hight[top] != hight[i]) hight[++top] = hight[i]; 46 } 47 for(int i = 1; i <= top; i++) //选取 48 { 49 ans += ((i == 1) || (i == top) || (hight[i-1] < hight[i] && hight[i] > hight[i+1]) || (hight[i-1] > hight[i] && hight[i] < hight[i+1])); 50 } 51 write(ans); 52 53 return 0; 54 } 55 /* 56 题目说什么2i,2i-1,2i+1。搞得很难看懂 57 其实就是说一个数比前一个数小的同时比后一个数大,或者比前一个数大的同时比后一个数小,这样的波浪形序列是满足条件的。 58 */