5016. 数列

来源:互联网 发布:tower windows 破解版 编辑:程序博客网 时间:2024/05/16 07:15

题目大意

给定一个长度为n的数列,依次将数列写在黑板上,每次可以将当前这个数写在已有数列的前面或者后面。求最终得到的数列的最长上升子序列是多长,有多少种方案可以得到这个长度的最长上升子序列。

Data Constraint
n200000

题解

对于一个位置i,它最终所能构成的最长上升子序列必定是由以它为起始位置的最长上升子序列和以它为起始位置的最长下降子序列拼接而成,分别设长度为len1,len2。那么当前可以贡献的长度是len1+len21,其余的n(len1+len21)个数都可以任放。所以用树状数组维护即可。

时间复杂度:O(nlogn)

SRC

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std ;#define N 200000 + 10typedef 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 ;}

以上.

1 0
原创粉丝点击