题意:一个士兵列队,因为高度导致参差不齐,长官要求最少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
7
using namespace std;
8
int lis[N],lds[N];
9
double w[N];
10
11
int 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
22
int 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
}