[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,表示每株花的高度。
第二行包含 个整数,依次为ℎ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 ",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 }