枚举每个位置,求以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; }