hdu5542 The Battle of Chibi
传送门
题意
给出一个长度为(n)的序列(a),计算其中长度为(m)的严格单调递增子序列的个数
(1leq nleq 1000,1leq a_ileq 1e9)
题解
设(dp[i][j])表示以(i)结尾,长度为(j)的子序列个数,则状态转移方程:
(dp[i][j]=sum dp[k][j-1](1leq kleq i-1,a[k]<a[i]))
(i,j,k)三重循环,由于第二维一定是((j-1)),所以可以用树状数组优化掉一维,为每个(j)开一个树状数组,可以在(O(log n))的时间复杂度内得到(dp[i][j]),之后使用(dp[i][j])更新树状数组
时间复杂度(O(n^2log n))
#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<string>
#include<sstream>
#include<cmath>
#include<ctime>
#include<climits>
#include<algorithm>
#define LL long long
#define ULL unsigned long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define PLI pairB<LL,int>
#define pi acos(-1.0)
#define eps 1e-6
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=1010,mod=1e9+7;
int T,n,m,a[maxn],b[maxn],len;
LL bit[maxn][maxn],dp[maxn][maxn];
void add(int i,int j,int c){
while(j<len){
bit[i][j]=(bit[i][j]+c)%mod;
j+=lowbit(j);
}
}
LL query(int i,int j){
LL res=0;
while(j){
res=(res+bit[i][j])%mod;
j-=lowbit(j);
}
return res;
}
int main(){
scanf("%d",&T);
for(int cas=1;cas<=T;cas++){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i-1]=a[i];
}
sort(b,b+n);
len=unique(b,b+n)-b+1;
for(int i=1;i<=n;i++){
a[i]=lower_bound(b,b+len,a[i])-b+1;
}
memset(bit,0,sizeof(bit));
memset(dp,0,sizeof(dp));
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]+query(j-1,a[i]-1))%mod;
add(j,a[i],dp[i][j]);
}
}
LL ans=0;
for(int i=1;i<=n;i++){
ans=(ans+dp[i][m])%mod;
}
printf("Case #%d: %lld
",cas,ans);
}
}