HDU 4990 Ordered Subsequence --数据结构优化DP

题意:给一串数字,问长度为m的严格上升子序列有多少个

解法:首先可以离散化为10000以内,再进行dp,令dp[i][j]为以第i个元素结尾的长度为j的上升子序列的个数,

则有dp[i][j] = SUM(dp[k][j-1])  (a[k] < a[i] && k < i)

不可能直接遍历,所以考虑优化,可以看出dp方程相当于一个区间求和,所以可以用树状数组来优化。

代码:

#include <iostream>

#include <cmath>

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <cmath>

#include <algorithm>

#define SMod 123456789

#define lll __int64

using namespace std;

#define N 10007



lll c[N],a[N],b[N];

int n,m;

lll dp[N][104];



int lowbit(int x)

{

    return x & (-x);

}



void modify(int pos,lll val)

{

    while(pos <= n)

    {

        c[pos] += val;

        pos += lowbit(pos);

    }

}



lll getsum(int pos)

{

    lll res = 0;

    while(pos > 0)

    {

        res = (res+c[pos])%SMod;

        pos -= lowbit(pos);

    }

    return res;

}



int main()

{

    int i,j;

    while(scanf("%d%d",&n,&m)!=EOF)

    {

        for(i=1;i<=n;i++)

        {

            scanf("%I64d",&a[i]);

            b[i] = a[i];

        }

        sort(b+1,b+n+1);

        memset(dp,0,sizeof(dp));

        for(i=1;i<=n;i++)

            dp[i][1] = 1;

        for(j=2;j<=m;j++)

        {

            memset(c,0,sizeof(c));

            for(i=1;i<=n;i++)

            {

                int ind = lower_bound(b+1,b+n+1,a[i])-b;

                dp[i][j] = getsum(ind-1);

                modify(ind,dp[i][j-1]);

            }

        }

        lll ans = 0;

        for(i=1;i<=n;i++)

            ans = (ans + dp[i][m])%SMod;

        printf("%I64d\n",ans);

    }

    return 0;

}
View Code

 

你可能感兴趣的:(sequence)