hdu-4991 Ordered Subsequence(dp+树状数组)

题目链接:

Ordered Subsequence

Time Limit: 4000/2000 MS (Java/Others)  

  Memory Limit: 32768/32768 K (Java/Others)

Problem Description

A numeric sequence of ai is ordered if a1<a2<……<aN. Let the subsequence of the given numeric sequence (a1, a2,……, aN) be any sequence (ai1, ai2,……, aiK), where 1<=i1<i2 <……<iK<=N. For example, sequence (1, 7, 3, 5, 9, 4, 8) has ordered subsequences, eg. (1, 7), (3, 4, 8) and many others.

Your program, when given the numeric sequence, must find the number of its ordered subsequence with exact m numbers.

Input

Multi test cases. Each case contain two lines. The first line contains two integers n and m, n is the length of the sequence and m represent the size of the subsequence you need to find. The second line contains the elements of sequence - n integers in the range from 0 to 987654321 each.
Process to the end of file.
[Technical Specification]
1<=n<=10000
1<=m<=100

Output

For each case, output answer % 123456789.

Sample Input

3 2

1 1 2

7 3

1 7 3 5 9 4 8

Sample Output

2

12

题意:

求长为n的数组中的长度为m的单调递增子序列的个数;

思路:

跟又一次的CF一样,只不过这题还要离散化;

dp[i][j]表示以第j个结尾长为i的子序列的个数;

 

AC代码:

/*4991    655MS    9664K    1701 B    G++    2014300227*/
#include <bits/stdc++.h>
using namespace std;
const int N=1e4+5;
typedef long long ll;
const ll mod=123456789;
int n,m;
ll sum[N],dp[102][N];
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,ll num)
{
    while(x<=n)
    {
        sum[x]+=num;
        sum[x]%=mod;
        x+=lowbit(x);
    }
}
ll query(int x)
{
    ll s=0;
    while(x>0)
    {
        s+=sum[x];
        s%=mod;
        x-=lowbit(x);
    }
    return s;
}
struct node
{
    int num,pos,c,d;
};
node po[N];
int cmp1(node x,node y)
{
    if(x.num==y.num)return x.pos<y.pos;
    return x.num<y.num;
}
int cmp2(node x,node y)
{
    return x.pos<y.pos;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)scanf("%d",&po[i].num),po[i].pos=i;
        sort(po+1,po+n+1,cmp1);
        po[0].num=-1;
        for(int i=1;i<=n;i++)
        {
            if(po[i].num==po[i-1].num)
            {
                po[i].c=po[i-1].c;
            }
            else po[i].c=i;//po[i].c表示第一个跟po[i].num相同的数的位置;
            po[i].d=i;//表示po[i]插入时的位置;
        }
        sort(po+1,po+n+1,cmp2);
        for(int i=1;i<=n;i++)
        {
            dp[1][i]=1;
            update(po[i].d,1);
        }
        for(int i=2;i<=m;i++)
        {
            memset(sum,0,sizeof(sum));
            for(int j=1;j<=n;j++)
            {
                if(po[j].c>1)
                dp[i][j]=query(po[j].c-1);//转移方程;
                else dp[i][j]=0;
                update(po[j].d,dp[i-1][j]);//把dp[i-1][j]更新上去;
            }
        }
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            ans+=dp[m][i];
            ans%=mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
时间: 2024-07-28 12:52:47

hdu-4991 Ordered Subsequence(dp+树状数组)的相关文章

HDU 5125 Magic Ball DP+树状数组

由于只要找1~x 中的最大值,然后线段树又容易MLE,所以这里可以用树状数组搞. #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <set> #include <bitset> #include <queue> #include <stack> #include <string> #i

HDU 2227 Find the nondecreasing subsequences (DP+树状数组+离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2227 Find the nondecreasing subsequences                                  Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)                                             

树形DP+树状数组 HDU 5877 Weak Pair

1 //树形DP+树状数组 HDU 5877 Weak Pair 2 // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 3 // 这道题要离散化 4 5 #include <bits/stdc++.h> 6 using namespace std; 7 #define LL long long 8 typedef pair<int,int> pii; 9 const double inf = 12345678901234

HDU 6447 - YJJ&#39;s Salesman - [树状数组优化DP][2018CCPC网络选拔赛第10题]

Problem DescriptionYJJ is a salesman who has traveled through western country. YJJ is always on journey. Either is he at the destination, or on the way to destination.One day, he is going to travel from city A to southeastern city B. Let us assume th

hdu 3015 Disharmony Trees (离散化+树状数组)

Disharmony Trees Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 663    Accepted Submission(s): 307 Problem Description One day Sophia finds a very big square. There are n trees in the square. T

HDU 2852 KiKi&#39;s K-Number (树状数组 &amp;&amp; 二分)

题意:给出对容器的总操作次数n, 接下来是这n个操作.这里对于一个容器提供三种操作, 分别是插入.删除和查找.输入0  e表示插入e.输入1  e表示删除e,若元素不存在输出No Elment!.输入2  e  k表示查找比e大且第k大的数, 若不存在则输出Not Find! 分析:这里考虑树状数组做的原因是在第三个操作的时候, 只要我们记录了元素的总数, 那通过求和操作, 便能够高效地知道到底有多少个数比现在求和的这个数要大, 例如 tot - sum(3)就能知道整个集合里面比3大的数到底有

HDU 3584 Cube (三维 树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3584 Cube Problem Description Given an N*N*N cube A, whose elements are either 0 or 1. A[i, j, k] means the number in the i-th row , j-th column and k-th layer. Initially we have A[i, j, k] = 0 (1 <= i, 

HDU 5592 ZYB&#39;s Premutation(树状数组+二分)

题意:给一个排列的每个前缀区间的逆序对数,让还原 原序列. 思路:考虑逆序对的意思,对于k = f[i] - f[i -1],就表示在第i个位置前面有k个比当前位置大的数,那么也就是:除了i后面的数字之外,它是在剩下的数字当中第k+1大的. 知道这个之后,可以用树状数组来帮助找出剩下的数中第k大的数,刚开始我们可以让1-n中每个元素都标记为1,那么他们的前缀和就代表它是第几小.所以,我们可以对于他们的和来二分快速寻找第k大数.其实在树状数组里面是按照第(i-k)小来找的.找完之后要删除这个元素的

hdu 5592 ZYB&#39;s Game 树状数组

ZYB's Game Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5592 Description ZYB has a premutation P,but he only remeber the reverse log of each prefix of the premutation,now he ask you to restore the premutation