51nod_2369 奈芙莲的序列(动态规划)

奈芙莲的序列

Problem Description

有一天可爱的Nephren得到了一个序列,一开始,她取出序列的第一个数,形成一个新的序列B,然后取出序列A的第二个数,放在序列B的最左边或最右边,序列B此时有两个数,下一步,再取出序列A的第三个数放在序列B的最左边或最右边,……

现在的问题是,通过上面的步骤,可以得到B的最长上升子序列的长度是多少

Input

第一行,一个整数N.
第二行,N个整数,表示序列A。

Output

一行一个整数,表示最长上升子序列的长度

Sample Input

4
2 1 3 4

Sample Output

4

题解:

只考虑组成最长序列的那些数字,其他数字忽略。当最长的序列的第一个元素放入B序列后,剩下的数字要不比B小,靠左放;要不比B大,向右放;要不就不是最长序列的一部分。
将数组逆序,分别求出每个位置的LIS和最长下降子序列,设为dp1和dp2,结果为 d p 1 i + d p 2 i 1 dp1_i+dp2_i-1 的最大值。

#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-7
 
using namespace std;
typedef long long LL;   
typedef pair<int, int> P;
const int maxn = 200100;
const int mod = 1000000007;
int a[maxn], dp1[maxn], dp2[maxn], g1[maxn], g2[maxn];

int main()
{
    int n, i, j, k, pos;
    int top1 = 0, top2;
    scanf("%d", &n);
    for(i=1;i<=n;i++)
        scanf("%d", &a[i]);
    for(i=n;i>=1;i--){
        pos = lower_bound(g1, g1+top1, a[i])-g1;
        if(pos == top1)top1++;
        g1[pos] = a[i];
        dp1[i] = pos+1;
    }
    top2 = n;
    for(i=n;i>=1;i--){
        pos = upper_bound(g2+top2, g2+n, a[i])-g2;
        if(pos == top2)top2--;
        g2[pos-1] = a[i];
        dp2[i] = n-pos+1;
    }
    int ans = 1;
    for(i=1;i<=n;i++)
        ans = max(ans, dp1[i]+dp2[i]-1);
    printf("%d\n", ans);
    return 0;
}
发布了70 篇原创文章 · 获赞 11 · 访问量 2882

猜你喜欢

转载自blog.csdn.net/sigh_/article/details/105402870