UVa1471 防线(DP,LIS优化)

本题要求在一个长度为n的序列中,删除一段连续子序列,使得剩下的序列有一个长度最大的连续递增子序列。
这里写图片描述

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#define maxn 300000
#define inf 1e9+100
using namespace std;
typedef long long ll;
ll T,n,A[maxn],tmp,f[maxn],g[maxn],d[maxn],ans;
int main(){
    cin>>T;
    while(T--){
        cin>>n;

        for(int i=1;i<=n;i++) cin>>A[i];
        //计算i结尾的最长长度 g[]
        for(int i=1;i<=n;i++){
            if(i==1) g[1]=1;
            else if(A[i]>A[i-1]) g[i]=g[i-1]+1;
            else g[i]=1;
        }
        //计算i开头的最长长度 f[]
        for(int i=n;i>=1;i--){
            if(i==n) f[i]=1;
            else if(A[i]<A[i+1]) f[i]=f[i+1]+1;
            else f[i]=1;
        } 
        for(int i=1;i<=n;i++) d[i]=inf;
        //solve,O(nlogn)
        d[1]=A[1];
        ans=1;
        for(int i=2;i<=n;i++){
            ll len=lower_bound(d+1,d+1+n,A[i])-d;
            ans=max(ans,len-1+f[i]);
            d[g[i]]=min(A[i],d[g[i]]);
        }
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37360631/article/details/81743625