hdu5542 树状数组优化dp
hdu5542 The Battle of Chibi
传送门
题意
给出一个长度为\(n\)的序列\(a\),计算其中长度为\(m\)的严格单调递增子序列的个数
\(1\leq n\leq 1000,1\leq a_i\leq 1e9\)
题解
设\(dp[i][j]\)表示以\(i\)结尾,长度为\(j\)的子序列个数,则状态转移方程:
\(dp[i][j]=\sum dp[k][j-1](1\leq k\leq i-1,a[k]<a[i])\)
\(i,j,k\)三重循环,由于第二维一定是\((j-1)\),所以可以用树状数组优化掉一维,为每个\(j\)开一个树状数组,可以在\(O(\log n)\)的时间复杂度内得到\(dp[i][j]\),之后使用\(dp[i][j]\)更新树状数组
时间复杂度\(O(n^2\log 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\n",cas,ans);
}
}