题目链接:https://vjudge.net/problem/POJ-1836
题意:给定n个数组成的序列,求最少减掉几个人,使得序列先单调递增再单调递减。
思路:枚举i:1..n,以i为边界,左边递增,右边递减,两次LIS即可,用O(nlogn)的做法,求结果最小即可。总时间复杂度O(n^2logn)。
AC代码:
#include<cstdio> #include<algorithm> using namespace std; const int maxn=1e3+5; int n,ans,len; double a[maxn],dp[maxn]; void clear(){ len=0; for(int i=0;i<=n;++i) dp[i]=0; dp[0]=-1; } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%lf",&a[i]); for(int i=0;i<=n;++i){ int res=0; clear(); for(int j=1;j<=i;++j){ if(a[j]>dp[len]) dp[++len]=a[j]; else if(a[j]<=dp[1]) dp[1]=a[j]; else{ int l=1,r=len,mid; while(l<=r){ mid=(l+r)>>1; if(dp[mid]>=a[j]) r=mid-1; else l=mid+1; } dp[l]=a[j]; } } res+=len; clear(); for(int j=n;j>i;--j){ if(a[j]>dp[len]) dp[++len]=a[j]; else if(a[j]<=dp[1]) dp[1]=a[j]; else{ int l=1,r=len,mid; while(l<=r){ mid=(l+r)>>1; if(dp[mid]>=a[j]) r=mid-1; else l=mid+1; } dp[l]=a[j]; } } res+=len; ans=max(ans,res); } printf("%d ",n-ans); return 0; }