poj1836 Alignment(LIS)

题目链接: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;
}
原文地址:https://www.cnblogs.com/FrankChen831X/p/11409098.html