AmazingCounters.com

NOIp2013 T5 花匠

[NOIP2013T5]花匠

Time Limit: 1000ms    Memory Limit: 131072KB
描述Descript.

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

具体而言,栋栋的花的高度可以看成一列整数ℎ1, ℎ2, … , ℎn。设当一部分花被移走后,剩下的花的高度依次为g1, g2, … , gm,则栋栋希望下面两个条件中至少有一个满足:

条件 A:对于所有的1 ≤ i ≤ m/2,g2i > g2i−1,且g2i > g2i+1

条件 B:对于所有的1 ≤ i ≤ m/2,g2i < g2i−1,且g2i < g2i+1

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

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

输入Input
输入的第一行包含一个整数 ,表示开始时花的株数。 
第二行包含 个整数,依次为ℎ1, ℎ2,… , ℎn,表示每株花的高度。
输出Output
输出一行,包含一个整数m,表示最多能留在原地的花的株数。
样例Sample

输入数据


5 
5 3 2 1 2 

输出数据


3
备注Hint

【输入输出样例说明】

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

 

【数据范围】

对于 20%的数据,n ≤ 10;

对于 30%的数据,n ≤ 25;

对于 70%的数据,n ≤ 1000,0 ≤ ℎi ≤ 1000;

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

 

裸dp+线段树

 1 #include<queue>
 2 #include<vector>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<iostream>
 7 #include<algorithm>
 8 using namespace std;
 9 const int N = 200010;
10 #define Ch1 T[kth].lc[i]
11 #define Ch2 T[kth].rc[i]
12 #define For(i,n) for(int i=1;i<=n;i++)
13 #define Rep(i,l,r) for(int i=l;i<=r;i++)
14 
15 struct tnode{
16     int l[N],r[N],mid[N];
17     int max[N],rt,lc[N],rc[N];
18 }T[2];
19 
20 struct flower{
21     int h,id,rh;
22 }p[N];
23 
24 bool fcmp(flower A,flower B){return A.rh<B.rh;}
25 bool scmp(flower A,flower B){return A.id<B.id;}
26 int Lim,n,cnt,f[N][2];
27 
28 void init(){
29     scanf("%d",&n);
30     For(i,n) {
31         scanf("%d",&p[i].rh);
32         p[i].id=i;
33     }
34     sort(p+1,p+n+1,fcmp);
35     p[1].h=1;
36     Rep(i,2,n)
37       if(p[i].rh==p[i-1].rh) p[i].h=p[i-1].h;
38       else                   p[i].h=p[i-1].h+1;
39     Lim=p[n].h;
40     sort(p+1,p+n+1,scmp);
41 }
42 
43 void Build(int kth,int &i,int l,int r){
44     i=++cnt;
45     T[kth].l[i]=l;T[kth].r[i]=r;T[kth].mid[i]=(l+r)>>1;
46     if(l==r) return;
47     Build(kth,Ch1,l,T[kth].mid[i]);Build(kth,Ch2,T[kth].mid[i]+1,r);
48 }
49 
50 void Modify(int kth,int i,int x,int delta){
51     if(T[kth].l[i]==T[kth].r[i]){
52         T[kth].max[i]=max(T[kth].max[i],delta);
53         return;
54     }
55     if(x<=T[kth].mid[i]) Modify(kth,Ch1,x,delta);
56     else                 Modify(kth,Ch2,x,delta);
57     T[kth].max[i]=max(T[kth].max[Ch1],T[kth].max[Ch2]);
58 }
59 
60 int query(int kth,int i,int l,int r){
61     if(l>r) return 0;
62     if(l==T[kth].l[i]&&r==T[kth].r[i]) return T[kth].max[i];
63     if(r<=T[kth].mid[i]) return query(kth,Ch1,l,r);else
64     if(l>T[kth].mid[i])  return query(kth,Ch2,l,r);else
65     return max(query(kth,Ch1,l,T[kth].mid[i]),query(kth,Ch2,T[kth].mid[i]+1,r));
66 }
67 
68 void DP(){
69     f[1][0]=1;
70     f[1][1]=1;
71     Modify(0,T[0].rt,p[1].h,1);
72     Modify(1,T[1].rt,p[1].h,1);
73     Rep(i,2,n){
74         f[i][0]=query(1,T[1].rt,p[i].h+1,Lim)+1;
75         Modify(0,T[0].rt,p[i].h,f[i][0]);
76         f[i][1]=query(0,T[0].rt,1,p[i].h-1)+1;
77         Modify(1,T[1].rt,p[i].h,f[i][1]);
78     }
79     printf("%d\n",max(f[n][0],f[n][1]));
80 }
81 
82 int main(){
83     init();
84     Build(0,T[0].rt,1,Lim);cnt=0;
85     Build(1,T[1].rt,1,Lim);
86     DP();
87     return 0;
88 }

 

posted @ 2014-11-04 10:57  ZJDx1998  阅读(276)  评论(0编辑  收藏  举报