POJ 1836 Alignment LIS变形(最长上升子序列)
题意:给 n 个数然后 让你求至少删除多少个数使剩下的数
可以满足在自己的位子上可以看到最左边或最右边的人
看到最边上人 的条件是某一边上的人都比自己矮
思路: 这道题是 LIS 的变形只需要求出 在每个位置上的 左边的最长上升子序列个数
加上 右边的最长下降子序列的个数
最后 n - 去他们就可以了
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define exp
using namespace std;
int bsearch(int low,int high,double x,double a[])
{
while(high>=low)
{
int mid=(high+low)/2;
if(a[mid]==x)
return mid;
else if(a[mid]<x)
low=mid+1;
else
high=mid-1;
}
return low;
}
double a[1100];
int ilen[1100];
double len[1100];
int dlen[1100];
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
scanf("%lf",&a[i]);
int ilenth=1;
len[1]=a[1];
ilen[1]=1;
for(int i=2;i<=n;i++)
{
if(len[ilenth]<a[i])
len[++ilenth]=a[i];
else
{
int flag=bsearch(1,ilenth,a[i],len);
len[flag]=a[i];
}
ilen[i]=ilenth;
}
int dlenth=1;
len[1]=a[n];
dlen[n]=1;
for(int i=n-1;i>=1;i--)
{
if(len[dlenth]<a[i])
len[++dlenth]=a[i];
else
{
int flag=bsearch(1,dlenth,a[i],len);
len[flag]=a[i];
}
dlen[i]=dlenth;
}
int Max=-1;
ilen[0]=0;
for(int i=1;i<=n;i++)
{
Max=max(Max,dlen[i]+ilen[i-1]);
}
printf("%d\n",n-Max);
}
return 0;
}