题目大意
给定一个长度为 n 的数列,依次将数列写在黑板上,每次可以将当前这个数写在已有数列的前面或者后面。求最终得到的数列的最长上升子序列是多长,有多少种方案可以得到这个长度的最长上升子序列。
Data Constraint
题解
对于一个位置
i
,它最终所能构成的最长上升子序列必定是由以它为起始位置的最长上升子序列和以它为起始位置的最长下降子序列拼接而成,分别设长度为
时间复杂度: O(nlogn)
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;
#define N 200000 + 10
typedef long long ll ;
const int MO = 1e9 + 7 ;
struct Note {
int v , h ;
} tp[N] ;
struct Stype {
int v , tot ;
Stype ( int X = 0 , int Y = 0 ) { v = X , tot = Y ; }
} T[2][N] ;
int A[N] , Tab[N] ;
int n , Cnt , ans1 , ans2 ;
bool cmp( Note a , Note b ) { return a.v < b.v ; }
Stype Find( int type , int x ) {
Stype ret ;
ret.v = 0 , ret.tot = 1 ;
while ( x ) {
if ( T[type][x].v > ret.v ) {
ret = T[type][x] ;
} else if ( T[type][x].v == ret.v ) ret.tot = (ret.tot + T[type][x].tot) % MO ;
x -= x & (-x) ;
}
return ret ;
}
void Insert( int type , int x , Stype val ) {
while ( x <= Cnt ) {
if ( val.v > T[type][x].v ) {
T[type][x].v = val.v ;
T[type][x].tot = val.tot ;
} else if ( val.v == T[type][x].v ) {
T[type][x].tot = (T[type][x].tot + val.tot) % MO ;
}
x += x & (-x) ;
}
}
int main() {
freopen( "sequence.in" , "r" , stdin ) ;
freopen( "sequence.out" , "w" , stdout ) ;
scanf( "%d" , &n ) ;
Tab[0] = 1 ;
for (int i = 1 ; i <= n ; i ++ ) Tab[i] = Tab[i-1] * 2 % MO ;
for (int i = 1 ; i <= n ; i ++ ) {
scanf( "%d" , &A[i] ) ;
tp[i].v = A[i] , tp[i].h = i ;
}
sort( tp + 1 , tp + n + 1 , cmp ) ;
tp[0].v = -1 ;
for (int i = 1 ; i <= n ; i ++ ) {
if ( tp[i].v != tp[i-1].v ) ++ Cnt ;
A[tp[i].h] = Cnt ;
}
Cnt ++ ;
for (int i = n ; i >= 1 ; i -- ) {
Stype ret0 = Find( 0 , Cnt - (A[i] + 1) ) ;
Stype ret1 = Find( 1 , A[i] - 1 ) ;
int len = ret0.v + ret1.v + 1 ;
if ( len > ans1 ) {
ans1 = len ;
ans2 = ((ll)ret0.tot * ret1.tot % MO * Tab[n-len]) % MO ;
} else if ( len == ans1 ) {
ans2 = (ans2 + ((ll)ret0.tot * ret1.tot % MO * Tab[n-len]) % MO) % MO ;
}
Insert( 0 , Cnt - A[i] , Stype( ret0.v + 1 , ret0.tot ) ) ;
Insert( 1 , A[i] , Stype( ret1.v + 1 , ret1.tot ) ) ;
}
printf( "%d %d\n" , ans1 , ans2 ) ;
return 0 ;
}
以上.