hihocoder_offer收割编程练习赛53_3 最长一次上升子序列

题目链接: https://hihocoder.com/contest/offers53/problem/3

解题思路: 最长一次上升子序列,必然是一个先下降,然后上升一次,然后接着下降的序列。这就把原问题分解成两个子问题,求1--i的最长下降子序列,和i到n-1的最长下降子序列,然后拼起来求一个最大值。还有一个特殊的情况,所有的序列都是下降的,此时就是整个序列的长度。

#include <bits/stdc++.h>
using namespace std;

const int imax_n = 100005;

int a[imax_n];
int b[imax_n];
int da[imax_n];
int db[imax_n];
int pb[imax_n];
int n;

int x[imax_n];
int cnt;

int b_search(int x[], int n, int k)
{
    int l = 0;
    int r = n - 1;
    while (l <= r)
    {
        int mid = l + (r - l) / 2;
        // printf("l=%d, r=%d, a[mid] = %d, k = %d\n", l, r, x[mid], k);
        if (x[mid] <= k)
        {
            l = mid + 1;
        }
        else
        {
            r = mid  - 1;
        }
    }
    return l;
}

void findLongestIns(int a[], int da[], int n)
{
    da[0] = 1;
    cnt = 0;
    x[cnt++] = a[0];
    for (int i = 1; i < n; ++i)
    {
        int pos = b_search(x, cnt, a[i]);
        da[i] = pos + 1;
        if (pos == cnt)
        {
            x[cnt++] = a[i];
        }
        else if (a[i] < x[pos])
        {
            x[pos] = a[i];
        }
    }
}

int p_search(int x[], int n, int k)
{
    int l = 0;
    int r = n-1;
    while (l <= r)
    {
        int mid = l + (r - l) / 2;
        if (x[mid] >= k)
        {
            l = mid + 1;
        }
        else
        {
            r = mid - 1;
        }
    }
    return l;
}

void findLongestDes(int a[], int da[], int n)
{
    da[0] = 1;
    cnt = 0;
    x[cnt++] = a[0];
    for (int i = 1; i < n ; ++i)
    {
        int pos = p_search(x, cnt, a[i]);
        da[i] = pos + 1;
        if (pos == cnt)
        {
            x[cnt++] = a[i];
        }
        else if (a[i] > x[pos])
        {
            x[pos] = a[i];
        }
    }
}

int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
    {
        scanf("%d", &a[i]);
        b[n - i - 1] = a[i];
    }
    findLongestDes(a, da, n);
//    for (int i = 0; i < n; ++i)
//    {
//        printf("%d ", da[i]);
//    }
//    printf("\n");
    findLongestIns(b, db, n);
//    for (int i = n-1; i >=0; i--)
//    {
//        printf("%d ", db[i]);
//    }
//    printf("\n");
    pb[0] = db[0];
    for (int i = 1; i < n; ++i)
    {
        pb[i] = max(pb[i-1], db[i]);
    }
//    for (int i = 0; i < n; ++i)
//    {
//        printf("%d ", pb[i]);
//    }
//    printf("\n");
    int ans = 0;
    for (int i = 1; i < n; ++i)
    {
        ans = max(ans, da[i-1] + pb[n - i - 1]);
    }
    ans = max(ans, db[0]);
    printf("%d\n", ans);
    return 0;
}

/*
    test
    5
    5 4 3 2 1
    5
    1 2 3 4 5

*/

 

posted @ 2018-04-01 18:58  只会一点暴力  阅读(249)  评论(0编辑  收藏  举报