题意:一个士兵列队,因为高度导致参差不齐,长官要求最少k个人出列,使得剩下的人在不改变相对次序的情况下,保证从左到右的高度保证严格满足 a1<a2<a3<...ai--ai+1>ai+2>ai+3>...>an。

   上面这条表达式出来之后就很容易想到LIS了,也就是枚举ai和ai+1的位置,然后左半部分和又半部分分别往相反的方向做LIS,求出出列数最短的一个中点即可,其中做LIS可以采用二分查找,使得转移花费从O(n)降为O(lg n)。
 

 1#include<cstdio>
 2#include<cstring>
 3#define inf 0x7fffffff
 4#define N 1001
 5#define MAX(a,b) (a<b)?b:a
 6#define MIN(a,b) (a<b)?a:b
 7using namespace std;
 8int lis[N],lds[N];
 9double w[N];
10
11int find(double c[],int len,double k){
12    int left=0,right=len,mid=(left+right)/2;
13    while(left<=right){
14        if( k>c[mid] ) left=mid+1;
15        else if( k<c[mid] ) right=mid-1;
16            else return mid; }
17        mid=(left+right)/2;
18    }

19    return left;
20}

21
22int main(){
23    int n,i,j,res;
24    int tmpDp[N];
25    double c[N];
26    while(scanf("%d",&n)!=EOF){
27        for(i=0;i<n;i++) scanf("%lf",&w[i]);
28        
29        for(i=0;i<=n;i++) c[i]=inf;
30        c[0]=-1; c[1]=w[n-1];
31        memset(tmpDp,0,sizeof(tmpDp));
32        tmpDp[n-1]=1;
33        for(i=n-2;i>-1;--i){
34            j=find(c,n+1,w[i]);
35            c[j]=w[i]; tmpDp[i]=j;
36        }

37        for(j=-1,i=n-1;i>-1;--i){ j=MAX(j,tmpDp[i]); lds[i]=j; }
38        
39        for(i=0;i<=n;i++) c[i]=inf;
40        c[0]=-1; c[1]=w[0];
41        memset(tmpDp,0,sizeof(tmpDp));
42        tmpDp[0]=1;
43        for(i=1;i<n;++i){
44            j=find(c,n+1,w[i]);
45            c[j]=w[i]; tmpDp[i]=j;
46        }

47        for(j=-1,i=0;i<n;++i){ j=MAX(j,tmpDp[i]); lis[i]=j; }
48
49        res=inf;
50        for(i=0;i<n;++i){
51            res=MIN(res,n-(lis[i]+lds[i+1]));
52        }

53        printf("%d\n",res);
54    }

55    return 0;
56}