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);
	}
}
posted @ 2020-08-30 19:53  fxq1304  阅读(34)  评论(0编辑  收藏  举报