uva 10534 (dp专组H题)

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sinat_30062549/article/details/51297743

题意:给一个长度为n的数字序列A,找到一个长度为2*k+1的子序列,使得前k+1个数单调上升,后k+1个数单调递减。输出2*k+1。

题解:

用cnt1[i]记录给定数组A到第i个元素,最长上升子序列的长度。求最长上升子序列的长度链接:http://blog.csdn.net/sinat_30062549/article/details/47193899

翻转数组A得到数组B

用cnt2[i]记录给定数组B到第i个元素,最长上升子序列的长度。

则,cnt[n-1-i]表示数组A中从i到n-1最长下降子序列的长度。

min(cnt1[i],cnt2[n-1-i])表示以第i个元素为中心的(k+1)的大小。

遍历i(0<=i<n)得到最大的k+1,记为ans。

输出2*ans-1为答案。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 10005;
int a[maxn];
int b[maxn];
int dp[maxn];
int cnt1[maxn];
int cnt2[maxn];
int n;

int lis(int *a){
    int len = 1;dp[1] = a[0];
    cnt1[0] = 1;
    for(int i = 1;i<n;i++){
        int t = a[i];
        if(t>dp[len]){dp[++len] = a[i];cnt1[i] = len;}
        else{
            int p = lower_bound(dp+1,dp+len+1,t)-dp;
            dp[p] = t;
            cnt1[i] = p;
        }
    }
    return len;
}
int main(){
    while(cin>>n){
        for(int i = 0;i<n;i++){
            cin>>a[i];
            b[n-1-i] = a[i];
        }
        int len1 = lis(a);
        for(int i = 0;i<n;i++){
            cnt2[i] = cnt1[i];
        }
        int len2 = lis(b);
       /* for(int i = n-1;i>=0;i--)
            cout<<cnt1[i]<<" ";
        cout<<endl;
        for(int i = 0;i<n;i++)
            cout<<cnt2[i]<<" ";
        cout<<endl;*/
        int ans = 0;
        for(int i = 0;i<n;i++){
            int mi = min(cnt2[i],cnt1[n-1-i]);
            ans = max(mi,ans);
        }
        cout<<ans*2-1<<endl;
    }
}



展开阅读全文

没有更多推荐了,返回首页