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\n", dp1[i], dp2[i] );

            //printf( "**%d %d\n", same1[i], same2[i] );

            ans = max( ans, dp1[i] + dp2[i] - min( same1[i], same2[i] ) );

        }



        printf( "%d\n", ans );

    }

    return 0;

}

 

你可能感兴趣的:(deque)