hdu5542 dp+二维树状数组

HDU5542
题意:求长度为m的上升子序列个数。
思路:用二维树状数组对于每个j建立一个树状数组,维护dp[i][j]前缀和。这个n只有1e3,可行。
Code:

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int AX = 1e3+6;
const int MOD = 1e9+7;
int c[AX][AX];
int dp[AX][AX];
int a[AX];
int b[AX];
int n , m ;
map<int,int>mp;
int tot ;
int get_id( int x ){
    if( !mp[x] ) mp[x] = ++tot;
    return mp[x] ;  
}

int lowbit(int x){
    return x & (-x);
}
void update( int i , int j , int val ){
    while( j <= n ){
        c[i][j] = ( c[i][j] + val ) % MOD;
        j += lowbit(j);
    }
}

LL getsum( int i , int j ){
    LL res = 0 ;
    while( j >= 1 ){
        res = ( res + c[i][j] ) % MOD;
        j -= lowbit(j);
    }
    return res ;
}
int main(){
    int T;
    scanf("%d",&T);
    int Case = 0 ;    
    while( T-- ){
        tot = 0;
        mp.clear();
        memset( c , 0 , sizeof(c) );
        memset( dp , 0 , sizeof(dp) );
        scanf("%d%d",&n,&m);
        for( int i = 1 ; i <= n ; i++ ){
            scanf("%d",&a[i]);
            b[i] = a[i];
        }
        sort( b + 1 , b + n + 1 );
        for( int i = 1 ; i <= n ; i++ ) b[i] = get_id(b[i]);
        for( int i = 1 ; i <= n ; i++ ) a[i] = get_id(a[i]);

        LL res = 0LL;

        for( int i = 1 ; i <= n ; i++ ){
            for( int j = 1 ; j <= m ; j++ ){
                if( j == 1 ) dp[i][j] = 1 ; 
                else dp[i][j] = ( dp[i][j] + getsum( j - 1 , a[i] - 1 ) ) % MOD ;
                update( j , a[i] , dp[i][j] );
            }
            res = ( res + dp[i][m] ) % MOD;
        }

        printf("Case #%d: %d\n",++Case,res);
    }
    return 0 ; 
}

猜你喜欢

转载自blog.csdn.net/FrankAx/article/details/81448450
今日推荐