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 ;
}