HDU 4604 deque 最长上升子序列

枚举每个位置,求以num[i]为起点的最长不下降子序列和以num[i]为结尾的最长不递增子序列。

并且把相同值的个数统计一下,最后要减去算重复了的。 

比如:

1

9

4 4 2 2 2 3 3 3 7

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAXN = 100000 + 10;

int n;
int num[MAXN];
int stack1[MAXN];
int stack2[MAXN];
int dp1[MAXN];
int dp2[MAXN];
int same1[MAXN];
int same2[MAXN];

void DP( int *stack, int *dp, int *same )
{
    int top = 0;

    stack[ ++top ] = num[0];

    dp[0] = 1;
    same[0] = 1;
    int temp;

    for ( int i = 1; i < n; i++ )
    {
        int x = upper_bound( stack + 1, stack + top + 1, num[i] ) - stack;
        int y = lower_bound( stack + 1, stack + top + 1, num[i] ) - stack;

        if ( num[i] >= stack[top] )
        {
            stack[ ++top ] = num[i];
            temp = top;
        }
        else
        {
            stack[x] = num[i];
            temp = x;
        }
        dp[i] = temp;
        same[i] = x - y + 1;
    }

    return;
}

int main()
{
    int T;
    scanf("%d", &T);
    while ( T-- )
    {
        scanf( "%d", &n );
        for ( int i = n - 1; i >= 0; --i )
            scanf( "%d", &num[i] );

        DP( stack1, dp1, same1 );

        for ( int i = 0; i < n; ++i )
        {
        //    printf( "%d ", num[i] );
            num[i] = -num[i];
        }
        //puts("");
        DP( stack2, dp2, same2 );

        int ans = 0;
        for ( int i = 0; i < n; ++i )
        {
            //printf( "%d %d
", dp1[i], dp2[i] );
            //printf( "**%d %d
", same1[i], same2[i] );
            ans = max( ans, dp1[i] + dp2[i] - min( same1[i], same2[i] ) );
        }

        printf( "%d
", ans );
    }
    return 0;
}
原文地址:https://www.cnblogs.com/GBRgbr/p/3209040.html