Ordered Subsequence

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 464    Accepted Submission(s): 216

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 的上升子序列.
题解:dp[i][j]代表以第 i 个元素结尾,长度为 j 的子序列 的个数。那么 dp[i][j] = sum(dp[k][j-1]) (1<=k<j).
但是这样的话我们直接枚举是 O(n*n*m)这样的时间复杂度是接受不了的。所以求和的那一层用树状数组优化成 O(n*log(n)*m)
/**
状态转移方程:
dp[i][j] = sum(dp[k][j-1]) (1<=k<i&&a[k]<a[i])
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL mod = ;
const int N = ;
const int M = ;
int cnt,n,m;
LL dp[N][M]; ///dp[i][j]代表第 i 个元素结尾,长度为 j 的递增子序列个数.
LL c[N],b[N],a[N]; LL lowbit(int i){
return i&(-i);
}
void update(int idx,int x,LL v){
for(int i=idx;i<=cnt;i+=lowbit(i)){
dp[i][x]=(dp[i][x]+v)%mod;
}
}
LL getsum(int idx,int x){
LL sum = ;
for(int i=idx;i>;i-=lowbit(i)){
sum=(sum+dp[i][x])%mod;
}
return sum;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
for(int i=;i<=n;i++){
scanf("%lld",&a[i]);
b[i] = a[i];
}
cnt = ;
for(int i=;i<=n;i++){ ///离散化 a 数组对应树状数组的 1 - cnt
if(b[i]!=b[i-]){
b[++cnt] = b[i];
}
}
sort(b+,b+cnt+);
memset(dp,,sizeof(dp));
for(int i=;i<=n;i++){
int idx = lower_bound(b+,b++cnt,a[i])-b;
for(int j=;j<=m;j++){
LL v;
if(j == ) v = ;
else v = getsum(idx-,j-);
update(idx,j,v);
}
}
LL ans = getsum(cnt,m);
printf("%lld\n",ans);
}
return ;
}
    #include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
#define LL long long
const int mod=;
int n,m;
int a[];
int b[],cnt; inline void Add(int &a,int b){
a=(a+b)%mod;
}
inline int lowbit(int x){
return x&(-x);
}
int sum[][];
inline void add(int id,int x,int v){
while(x<=cnt){
Add(sum[id][x],v);
x+=lowbit(x);
}
}
inline int query(int id,int x){
int ans=;
while(x){
Add(ans,sum[id][x]);
x-=lowbit(x);
}
return ans;
} int main(){
while(~scanf("%d%d",&n,&m)){
cnt=;
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
b[++cnt]=a[i];
}
sort(b+,b+cnt+);
cnt=(int)(unique(b+,b++cnt)-(b+));
for(int i=;i<=n;i++)a[i]=(int)(lower_bound(b+,b++cnt,a[i])-b); memset(sum,,sizeof sum); int ans=;
for(int i=;i<=n;i++){
for(int j=;j<m;j++){
if(a[i]>){
int sum=query(j,a[i]-);
add(j+,a[i],sum);
}
}
add(,a[i],);
}
ans=query(m,cnt);
printf("%d\n",ans);
}
return ;
}

hdu 4991(树状数组+DP)的更多相关文章

  1. hdu 2227(树状数组+dp)

    Find the nondecreasing subsequences Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/3 ...

  2. hdu 4638 树状数组 区间内连续区间的个数(尽可能长)

    Group Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

  3. hdu 4777 树状数组+合数分解

    Rabbit Kingdom Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  4. hdu 4622 Reincarnation trie树+树状数组/dp

    题意:给你一个字符串和m个询问,问你l,r这个区间内出现过多少字串. 连接:http://acm.hdu.edu.cn/showproblem.php?pid=4622 网上也有用后缀数组搞得. 思路 ...

  5. 2018 CCPC网络赛 1010 hdu 6447 ( 树状数组优化dp)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6447 思路:很容易推得dp转移公式:dp[i][j] = max(dp[i][j-1],dp[i-1][j ...

  6. 【树状数组+dp】HDU 5542 The Battle of Chibi

    http://acm.hdu.edu.cn/showproblem.php?pid=5542 [题意] 给定长为n的序列,问有多少个长为m的严格上升子序列? [思路] dp[i][j]表示以a[i]结 ...

  7. HDU 6348 序列计数 (树状数组 + DP)

    序列计数 Time Limit: 4500/4000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Subm ...

  8. hdu 3030 Increasing Speed Limits (离散化+树状数组+DP思想)

    Increasing Speed Limits Time Limit: 2000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java ...

  9. HDU 6447 YJJ’s Salesman (树状数组 + DP + 离散)

    题意: 二维平面上N个点,从(0,0)出发到(1e9,1e9),每次只能往右,上,右上三个方向移动, 该N个点只有从它的左下方格点可达,此时可获得收益.求该过程最大收益. 分析:我们很容易就可以想到用 ...

随机推荐

  1. Redis之String类型操作

    接口IRedisDaoStr: package com.net.test.redis.base.dao; import java.util.List; import java.util.Map; /* ...

  2. oracle insert用法总结

    总结下Oracle 中的Insert用法   1.标准Insert --单表单行插入   语法:     INSERT INTO table [(column1,column2,...)] VALUE ...

  3. Codeforces Round #461 (Div. 2) D. Robot Vacuum Cleaner

    D. Robot Vacuum Cleaner time limit per test 1 second memory limit per test 256 megabytes Problem Des ...

  4. [Poj3281]Dining(最大流)

    Description 有n头牛,f种食物,d种饮料,每头牛有nf种喜欢的食物,nd种喜欢的饮料,每种食物如果给一头牛吃了,那么另一个牛就不能吃这种食物了,饮料也同理,问最多有多少头牛可以吃到它喜欢的 ...

  5. 使用HTTP协议访问网路

    使用HTTP协议访问网路 一.使用HttpURLConnection //new一个URL对象 URL url = new URL("http://www.qq.com");//千 ...

  6. LINQ体验(9)——LINQ to SQL语句之Insert/Update/Delete操作

    我们继续讲解LINQ to SQL语句,这篇我们来讨论Insert/Update/Delete操作.这个在我们的程序中最为常用了.我们直接看例子. Insert/Update/Delete操作 插入( ...

  7. 二叉树遍历(Java实现)

    二叉树遍历(Java实现)   主要是二叉树的遍历,包括递归遍历和非递归遍历 import java.util.ArrayDeque; import java.util.ArrayList; impo ...

  8. C 语言 习题 1-14

    练习 1-14 编写一个程序,打印输入中各个字符出现频度的直方图. #include <stdio.h> /* count digits, white space, others */ i ...

  9. python 学习分享-实战篇简单的ftp

    import socket import os import time import pickle Basedb = os.path.dirname(os.path.dirname(os.path.a ...

  10. php获取当前操作系统类型

    如何使用 php 获取当前操作系统类型呢? 严格来说这里分两种情况,一种情况是获取 服务器端 的操作系统类型,一种是获取 客户端 的操作系统类型. 下面将对如何使用php获取这两种情况下的操作系统类型 ...