Reference:http://www.cnblogs.com/wuyiqi/archive/2012/03/28/2420916.html

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=2836

题目大意:计算序列有多少种组合,每个组合至少两个数,使得组合中相邻两个数之差不超过H,序列有重复的数。MOD 9901。

解题思路

朴素O(n^2)

以样例1 3 7 5为例,如果没有重复的数。

设dp[i]前n个数的方案数,初始化为1。

那么for(1...i...N)

$dp[i]=\sum dp[j]+1\quad,where \quad \left |num[i]-num[j] \right|<=H$

+1是为了计算两个点直接连接的情况,如样例:

dp[1]=1 (无连接)

dp[2]=dp[1]+1=2 (1-3连接)

dp[3]=1 (无连接)

dp[4]=dp[2]+dp[3]+1=4(1-3-5, 3-5,7-5)

如果没有+1,那么就没法dp下去,同时,这样每个点多算了1,所以ans=1+2+1+4-4=4

快速求和优化

上面O(n^2)的原因在于, 原始序列的dp区间不是连续的,比如1,3,8,3,5,7 H=2

5的dp区间可以是2,4,需要多扫一轮来找出这些离散的值。

实际上,dp过程中可以不依赖原始序列顺序。将原始序列排序离散化去重后,变成1,3,5,8

这样,新添加一个box的时候,可以二分找其值在新序列中边界L,R,这样,原本的离散dp求和,

被转化成了连续区间求和$\sum sum(R)-sum(L-1)$

原因很简单,5在实际计算时,在3,3,7中都被牵扯到,是一个对称计算。所以排序去重后可以简化为对连续区间的计算。

至于为什么要去重,主要是为了解决重值的重复计算(原题并没有说没有重值)

比如1,3,3,如果不去重,为第二个3单独开个dp状态,那么1-3被算了两次(dp初始值为1)

所以第二个3,无须再开一个dp状态,直接第一个3基础上算就行了。保证ans-n是最后的结果。

代码

#include "cstdio"
#include "algorithm"
#include "cstring"
using namespace std;
#define maxn 100005
#define mod 9901
int num[maxn],Hash[maxn],n,h,s[maxn];
int lowbit(int x) {return x&(-x);}
int sum(int x)
{
int ret=;
while(x>) ret=(ret+s[x])%mod,x-=lowbit(x);
return ret%mod;
}
void update(int x,int d)
{
while(x<=n) s[x]=(s[x]+d)%mod,x+=lowbit(x);
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d%d",&n,&h)!=EOF)
{
memset(Hash,,sizeof(Hash));
memset(s,,sizeof(s));
for(int i=;i<=n;i++)
{
scanf("%d",&num[i]);
Hash[i]=num[i];
}
sort(Hash+,Hash+n+);
int diff=unique(Hash+,Hash+n+)-Hash-;
int ans=;
for(int i=;i<=n;i++)
{
int idx=lower_bound(Hash+,Hash+diff+,num[i])-Hash;
int L=lower_bound(Hash+,Hash+diff+,num[i]-h)-Hash;
int R=upper_bound(Hash+,Hash+diff+,num[i]+h)-Hash-;
int dp=(sum(R)-sum(L-)+)%mod;
ans+=dp;
update(idx,dp);
}
printf("%d\n",(ans-n)%mod);
}
}

HDU 2836 (离散化DP+区间优化)的更多相关文章

  1. hdu 4833 离散化+dp ****

    先离散化,然后逆着dp,求出每个点能取到的最大利益,然后看有没有钱,有钱就投 想法好复杂 #include <stdio.h> #include <string.h> #inc ...

  2. HDU 2829 [Lawrence] DP斜率优化

    解题思路 首先肯定是考虑如何快速求出一段铁路的价值. \[ \sum_{i=1}^k \sum_{j=1, j\neq i}^kA[i]A[j]=(\sum_{i=1}^kA[i])^2-\sum_{ ...

  3. HDU 3480 Division DP斜率优化

    解题思路 第一步显然是将原数组排序嘛--然后分成一些不相交的子集,这样显然最小.重点是怎么分. 首先,我们写出一个最暴力的\(DP\): 我们令$F[ i ][ j ] $ 为到第\(i\)位,分成\ ...

  4. HDU.2829.Lawrence(DP 斜率优化)

    题目链接 \(Description\) 给定一个\(n\)个数的序列,最多将序列分为\(m+1\)段,每段的价值是这段中所有数两两相乘的和.求最小总价值. \(Solution\) 写到这突然懒得写 ...

  5. HDU3480_区间DP平行四边形优化

    HDU3480_区间DP平行四边形优化 做到现在能一眼看出来是区间DP的问题了 也能够知道dp[i][j]表示前  i  个节点被分为  j  个区间所取得的最优值的情况 cost[i][j]表示从i ...

  6. HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化)

    HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化) 题意分析 先把每种硬币按照二进制拆分好,然后做01背包即可.需要注意的是本题只需要求解可以凑出几种金钱的价格,而不需要输出种数 ...

  7. HDOJ(HDU).1059 Dividing(DP 多重背包+二进制优化)

    HDOJ(HDU).1059 Dividing(DP 多重背包+二进制优化) 题意分析 给出一系列的石头的数量,然后问石头能否被平分成为价值相等的2份.首先可以确定的是如果石头的价值总和为奇数的话,那 ...

  8. HDU 3507 [Print Article]DP斜率优化

    题目大意 给定一个长度为\(n(n \leqslant 500000)\)的数列,将其分割为连续的若干份,使得 $ \sum ((\sum_{i=j}^kC_i) +M) $ 最小.其中\(C_i\) ...

  9. R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数

    R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...

随机推荐

  1. php基础面试题1

    问题1:谈谈你对的PHP的基本认识. 回答:PHP是Hypertext Preprocessor(超文本预处理器)的简称,是一种用来开发动态网站的服务器端脚本语言. 问题2:什么是MVC? 回答:MV ...

  2. MVC基础知识 – 1.抽象工厂模式

    1.调用规则 2.简单工厂 问题:在List.aspx里怎么new一个业务层? 2.1.再在 02SBLL 解决方案里建一个类库 BLL_Tow,也有一个 Users.cs 2.2.建立一个工厂 2. ...

  3. ExcelReport第三篇:扩展元素格式化器

    导航 目   录:基于NPOI的报表引擎——ExcelReport 上一篇:ExcelReport源码解析 概述 上篇中已介绍了ExcelRepor的架构,本篇将通过例子讲述如何扩展元素格式化器以满足 ...

  4. JS手机浏览器判断(转)

    整理查询一下,js判断手机浏览器的方法 <script type="text/javascript"> /* * 智能机浏览器版本信息:包括微信内置 * */ var ...

  5. [LeetCode] Min Stack

    Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. pu ...

  6. HDU4008 Parent and son(树形DP LCA)

    先记录以1为根时每个节点子树儿子节点的最大与次小值,询问x, y时,先判断x在不在y的子树范围内,若不在,结果为y的儿子结点,后继的最小值. 若x在y的子树范围内,若y儿子最小值是x的前驱,从次小值与 ...

  7. 攻城狮在路上(壹) Hibernate(九)--- Hibernate的映射类型

    Hibernate采用映射类型作为Java类型和SQL类型的桥梁,对应type属性.分为两种:内置映射类型和客户化映射类型.一.内置映射类型: 1.Java基本类型的Hibernate映射类型: Ja ...

  8. php抓取网页信息

    index.php <?php include_once 'simple_html_dom.php'; //获取html数据转化为对象 $html = file_get_html('http:/ ...

  9. hdu 4027 2011上海赛区网络赛G 线段树 成段平方根 ***

    不能直接使用成段增减的那种,因为一段和的平方根不等于平方根的和,直接记录是否为1,是1就不需要更新了 #include<cstdio> #include<iostream> # ...

  10. hdu 4784 Dinner Coming Soon(spfa + 优先队列)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4784 思路:建图,对于同一个universe来说,就按题目给的条件相连,对于相邻的universe,连 ...