http://acm.hdu.edu.cn/showproblem.php?pid=5542

题意:求严格递增的长度为M的序列的组数。

当dp的优化方案不那么容易一眼看出来的时候,我们可以考虑先写一个朴素算法,在朴素算法的基础上去考虑优化。

正如这题,很显然用dp[i][j]存储长度为i的序列以j结尾的情况。

然后有两种方法去递推。

一种是从1--M序列的长度,对于每一个数字去寻找他前面比她小的数列进行递推,递推方程dp[i][j] += dp[i - 1][k]; (k < j && a[k] < a[j])

第二种方法是从1--N枚举每个数,对于每个数直接寻找他前面的所有满足上面k条件的数字进行递推。

两种方法时间复杂度相同,朴素算法都是T * M * N * N,显然会TLE,但是考虑在其中一层,也就是寻找他前面枚举条件的数这一步进行优化,当我们用树状数组维护前缀的和的时候,我们就可以把一层N优化变为lnN,总的时间复杂度变成O(TNMln(N));

        For(i,,M){
Mem(tree,);
if(i == ) add(,);
For(j,,N){
dp[i & ][j] = getsum(a[j] - ) % mod;
add(a[j],dp[i + & ][j]);
}
}

第一种方法的主要优化代码

    For(i,,N){
For(j,,M){
if(j == ) dp[j & ][i] = ;
else dp[j & ][i] = getsum(j - ,a[i] - ) % mod;
add(j,a[i],dp[j & ][i]);
}
}

第二种方法的主要优化代码

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = ;
const LL INF = 1e18;
const int mod = 1e9 + ;
int N,M,tmp,K;
LL a[maxn];
int cnt;
LL Hash[maxn];
inline LL read()
{
LL now=;register char c=getchar();
for(;!isdigit(c);c=getchar());
for(;isdigit(c);now=now*+c-'',c=getchar());
return now;
}
LL dp[][maxn];
LL tree[maxn];
void add(int x,LL t){
for(;x <= cnt + ; x += x & -x) tree[x] = (tree[x] + t) % mod;
}
LL getsum(int x){
LL s = ;
for(;x > ;x -= x & -x) s = (s + tree[x]) % mod;
return s;
}
int main()
{
int T; Sca(T);
int CASE = ;
while(T--){
Sca2(N,M);
For(i,,N) Hash[i] = a[i] = read();
sort(Hash + ,Hash + + N);
cnt = unique(Hash + ,Hash + + N) - Hash - ;
For(i,,N) a[i] = lower_bound(Hash + ,Hash + + cnt,a[i]) - Hash + ;
Mem(dp,);
For(i,,M){
Mem(tree,);
if(i == ) add(,);
For(j,,N){
dp[i & ][j] = getsum(a[j] - ) % mod;
add(a[j],dp[i + & ][j]);
}
}
LL ans = ;
For(i,,N) ans = (ans + dp[M & ][i]) % mod;
printf("Case #%d: ",CASE++);
Prl(ans);
}
#ifdef VSCode
system("pause");
#endif
return ;
}

HDU5542 BIT优化dp的更多相关文章

  1. bzoj-4518 4518: [Sdoi2016]征途(斜率优化dp)

    题目链接: 4518: [Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地 ...

  2. bzoj-1096 1096: [ZJOI2007]仓库建设(斜率优化dp)

    题目链接: 1096: [ZJOI2007]仓库建设 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L ...

  3. 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)

    D. Slalom time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...

  4. 单调队列优化DP,多重背包

    单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...

  5. [BZOJ3156]防御准备(斜率优化DP)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3156 分析: 简单的斜率优化DP

  6. 【BZOJ-1096】仓库建设 斜率优化DP

    1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3719  Solved: 1633[Submit][Stat ...

  7. 优化DP的奇淫技巧

    DP是搞OI不可不学的算法.一些丧心病狂的出题人不满足于裸的DP,一定要加上优化才能A掉. 故下面记录一些优化DP的奇淫技巧. OJ 1326 裸的状态方程很好推. f[i]=max(f[j]+sum ...

  8. bzoj1855: [Scoi2010]股票交易--单调队列优化DP

    单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w ...

  9. BZOJ 1010: [HNOI2008]玩具装箱toy 斜率优化DP

    1010: [HNOI2008]玩具装箱toy Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再 ...

随机推荐

  1. 双系统windows+linux如何正确删除linux

    双系统windows+linux如何正确删除linux 2017年11月16日 10:42:49 dovepym 阅读数:26363   之前在windows的基础上又安装了ubuntu系统16.04 ...

  2. P1064 金明的预算方案

    思路:就是一个背包问题  因为数据范围小,所以不把 1个带附着物的东西 拆成 带1个带2个或不带 #include<bits/stdc++.h> using namespace std; ...

  3. 【BZOJ3456】轩辕朗的城市规划 无向连通图计数 CDQ分治 FFT 多项式求逆 多项式ln

    题解 分治FFT 设\(f_i\)为\(i\)个点组成的无向图个数,\(g_i\)为\(i\)个点组成的无向连通图个数 经过简单的推导(枚举\(1\)所在的连通块大小),有: \[ f_i=2^{\f ...

  4. awk文本分析工具

    Usage:awk [option] 'program' file ... awk [option] -f progfile file ... [optin]: -F fs 指定输入分隔符,fs可是字 ...

  5. 【UOJ#311】【UNR #2】积劳成疾(动态规划)

    [UOJ#311][UNR #2]积劳成疾(动态规划) UOJ Solution 考虑最大值分治解决问题.每次枚举最大值所在的位置,强制不能跨过最大值,左右此时不会影响,可以分开考虑. 那么设\(f[ ...

  6. 「ZJOI2015」地震后的幻想乡 解题报告

    「ZJOI2015」地震后的幻想乡 想了半天,打开洛谷题解一看,最高票是_rqy的,一堆密密麻麻的积分差点把我吓跑. 据说有三种解法,然而我只学会了一种最辣鸡的凡人解法. 题意:给一个无向图\(G\) ...

  7. luogu4145 上帝造题的七分钟2 (线段树)

    题意:给一个数列,维护两个操作,区间开根号.询问区间和 注意到1e12开根号六次后就变成1,而且根号1等于1 也就是说,就算我们用单点修改,只要跳过1,那么修改的次数最多也就是6n 那么维护一个区间最 ...

  8. 牛客小白月赛6C-桃花(DFS/BFS求树的直径)

    链接:https://www.nowcoder.com/acm/contest/136/C 来源:牛客网 桃花 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言 ...

  9. Ubuntu16.04下的NetCore环境搭建(附录含Ubuntu 18.04 安装 NetCore2.1)

    跨平台系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#linux VSCode安装:http://www.cnblogs.com/dunitia ...

  10. spring data jpa 分页查询

    https://www.cnblogs.com/hdwang/p/7843405.html spring data jpa 分页查询   法一(本地sql查询,注意表名啥的都用数据库中的名称,适用于特 ...