HDOJ5542-The Battle of Chibi【树状数组,dp】

正题

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5542


题目大意

求序列A有多少个长度为M的递增子序列。


解题思路

fi,j f i , j 表示长度为i,以 Aj A j 结尾的序列的个数。然后显然得出动态转移方程通过上一次从任意一个地方转移,动态转移方程:

fi,j=k<j,Ak<Ajfi1,k f i , j = ∑ k < j , A k < A j f i − 1 , k

我们可以用树状数组储存和维护k。


code

#include
#include
#include
#define N 2010
#define lowbit(x) x&-x
#define BPM 1000000007
using namespace std;
int t[N],a[N],f[N][N],n,m,l,uiqe[N],ans,ts;
void change(int x,int k)
{
    while(x<=l)
    {
        t[x]=(t[x]+k)%BPM;
        x+=lowbit(x);
    }
}
int ask(int x)
{
    int sum=0;
    while(x)
    {
        sum=(sum+t[x])%BPM;
        x-=lowbit(x);
    }
    return sum;
}
int main()
{
    scanf("%d",&ts);
    for(int ti=1;ti<=ts;ti++)
    {
        scanf("%d%d",&n,&m);
        a[0]=-2147483647;uiqe[n+1]=a[0];
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]),uiqe[i]=a[i];
        sort(uiqe+1,uiqe+2+n);
        l=unique(uiqe+1,uiqe+1+n)-(uiqe+1);
        for(int i=0;i<=n;i++)
            a[i]=lower_bound(uiqe+1,uiqe+1+l,a[i])-uiqe;
        //以上为离散化
        memset(f,0,sizeof(f));
        f[0][0]=1;ans=0;
        for(int i=1;i<=m;i++){
              memset(t,0,sizeof(t));
            change(a[0],f[i-1][0]);//修改
            for(int j=1;j<=n;j++){
                f[i][j]=ask(a[j]-1);//询问和
                change(a[j],f[i-1][j]);//维护和
                if(i==m) ans=(ans+f[i][j])%BPM;
            }
          }
          printf("Case #%d: %d\n",ti,ans);
    }
}

你可能感兴趣的:(dp,数据结构,树状数组,hdu,dp)