HDU4991 Ordered Subsequence (dp+樹狀陣列+離散化)

bigbigship發表於2014-09-08

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=4991

題目的意思是求長度為 m 的上升序列有多少個;

設DP[I][J]表示 以第i個元素結尾的 長度為j的序列的個數

dp[i][j]=sum(dp[k][j-1])  (i>k &&a[i]>a[k])

數字有1萬個,先離散化一下,把所有數字對應到1到n之間,然後用陣列陣列進行求和就好
程式碼如下:
#include <iostream>
#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>

using namespace std;

const int N = 10010;

const int mod = 123456789;

typedef long long LL;

LL c[N],a[N],b[N];
int n,m;
LL dp[N][104];

int lowbit(int x)
{
    return x & (-x);
}

void update(int pos,LL val)
{
    while(pos <= n)
    {
        c[pos] += val;
        pos += lowbit(pos);
    }
}

LL query(int pos)
{
    LL res = 0;
    while(pos > 0)
    {
        res = (res+c[pos])%mod;
        pos -= lowbit(pos);
    }
    return res;
}

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int 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(int i=1;i<=n;i++)
            dp[i][1] = 1;
        for(int j=2;j<=m;j++)
        {
            memset(c,0,sizeof(c));
            for(int i=1;i<=n;i++)
            {
                int ind = lower_bound(b+1,b+n+1,a[i])-b;
                dp[i][j] = query(ind-1);
                update(ind,dp[i][j-1]);
            }
        }
        LL ans = 0;
        for(int i=1;i<=n;i++)
            ans = (ans + dp[i][m])%mod;
        printf("%I64d\n",ans);
    }
    return 0;
}


相關文章