来源:http://blog.csdn.net/y990041769/article/details/38405063

RMQ算法,是一个快速求区间最值的离线算法,预处理时间复杂度O(n*log(n)),查询O(1),所以是一个很快速的算法,当然这个问题用线段树同样能够解决。

问题:给出n个数ai,让你快速查询某个区间的的最值。

算法分类:DP+位运算

算法分析:这个算法就是基于DP和位运算符,我们用dp【i 】【j】表示从第 i 位开始,到第 i + 2^j -1 位的最大值或者最小值。

那么我求dp【i】【j】的时候可以把它分成两部分,第一部分从 i 到 i + 2 ^( j-1 ) - 1 ,第二部分从 i + 2 ^( j-1 )  到 i + 2^j - 1 次方,其实我们知道二进制数后一个是前一个的二倍,那么可以把 i ---  i + 2^j  这个区间 通过2^(j-1) 分成相等的两部分, 那么转移方程很容易就写出来了。

转移方程: mm [ i ] [ j ] = max ( mm [ i ] [ j - 1 ] , mm [ i + ( 1 << ( j - 1 ) ) ] [ j - 1 ] );

代码:

void rmq_isit(bool ok)
{
for(int i=;i<=n;i++)
mm[i][]=mi[i][]=a[i];
for(int j=;(<<j)<=n;j++)
{
for(int i=;i+(<<j)-<=n;i++)
{
if(ok)
mm[i][j]=max(mm[i][j-],mm[i+(<<(j-))][j-]);
else
mi[i][j]=min(mi[i][j-],mi[i+(<<(j-))][j-]);
} }
}

那么查询的时候对于任意一个区间 l -- r ,我们同样可以得到区间差值 len = (r - l + 1)。

那么我们这一用小于2^k<=len,的 k 把区间分成可以交叉的两部分l 到 l+ (1<<k) -1, 到 r -(1<<k)+1 到 r 的两部分,很easy的求解了。

查询代码:

int rmq(int l,int r)
{
int k=;
while((<<(k+))<=r-l+)
k++;
//printf("%d %d %d %d\n",l,l+(1<<k),r-(1<<k)+1,r-(1<<k)+1+(1<<k));
int ans1=max(mm[l][k],mm[r-(<<k)+][k]);
int ans2=min(mi[l][k],mi[r-(<<k)+][k]);
return ans1-ans2;
}

例题: POJ Balanced Lineup

ac代码

#include <iostream>
#include <algorithm>
using namespace std; const int maxn = ;
int a[maxn],mx[maxn][],mn[maxn][];
int n,m; int main(){
ios::sync_with_stdio();//c++ 关同步 ac
cin.tie();
cout.tie();
cin>>n>>m;
for(int i=;i<=n;i++)
{
cin>>a[i];
mx[i][]=mn[i][]=a[i];
}
for(int j=; (<<j)<=n; j++)
{
for(int i=;i+(<<j)-<=n;i++)
{
mx[i][j]=max(mx[i][j-],mx[i+(<<(j-))][j-]);
mn[i][j]=min(mn[i][j-],mn[i+(<<(j-))][j-]);
}
}
for(int i=;i<=m;i++)
{
int le,ri;
cin>>le>>ri;
int len = ri-le+;
int k=;
while((<<(k+))<=len)
k++;
int ans1=max(mx[le][k],mx[ri-(<<k)+][k]);
int ans2=min(mn[le][k],mn[ri-(<<k)+][k]);
cout<<ans1-ans2<<endl;
} return ;
}

 

基于DP+位运算的RMQ算法的更多相关文章

  1. [BZOJ1151][CTSC2007]动物园zoo 解题报告|DP|位运算

    Description 最近一直在为了学习算法而做题,这道题是初一小神犇让我看的.感觉挺不错于是写了写. 这道题如果是一条线的话我们可以构造一个DP f[i,j]表示以i为起点,i,i+1...i+4 ...

  2. HDU 5735 Born Slippy(拆值DP+位运算)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5735 [题目大意] 给出一棵树,树上每个节点都有一个权值w,w不超过216,树的根为1,从一个点往 ...

  3. [poj 1185] 炮兵阵地 状压dp 位运算

    Description 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用&quo ...

  4. HDU 5119 Happy Matt Friends(dp+位运算)

    题意:给定n个数,从中分别取出0个,1个,2个...n个,并把他们异或起来,求大于m个总的取法. 思路:dp,背包思想,考虑第i个数,取或者不取,dp[i][j]表示在第i个数时,异或值为j的所有取法 ...

  5. hdu 4336 Card Collector (概率dp+位运算 求期望)

    题目链接 Card Collector Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  6. RMQ算法区间最值

    问题类型:是多次询问一个大区间里子区间的最值问题 dp + 位运算的思想处理 rmax[i][j]表示从i开始到i + 2^j - 1的区间里的最大值dp[i][j] ==== (i,i + 2^j ...

  7. Linux - Shell - 算数表达式 - 位运算

    概述 shell 中基于 $(()) 的 位运算 背景 复习 shell 脚本 凑数吧 准备 环境 os centos7 1. 位运算 代码 #!/bin/bash # 位运算 arg1=2 arg2 ...

  8. 【科技】位运算(bitset)优化最长公共子序列算法

    最长公共子序列(LCS)问题 你有两个字符串 \(A,B\),字符集为 \(\Sigma\),求 \(A, B\) 的最长公共子序列. 简单动态规划 首先有一个广为人知的 dp:\(f_{i,j}\) ...

  9. bzoj5108 [CodePlus2017]可做题 位运算dp+离散

    [CodePlus2017]可做题 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 87  Solved: 63[Submit][Status][Dis ...

随机推荐

  1. 脱壳系列_2_IAT加密壳_详细版_解法1_包含脚本

    1 查看壳程序信息 使用ExeInfoPe 分析: 发现这个壳的类型没有被识别出来,Vc 6.0倒是识别出来了,Vc 6.0的特征是 入口函数先调用GetVersion() 2 用OD找OEP 拖进O ...

  2. ubuntu/deepin 下下载wxpython

    1 输入apt-cache search wxpython 如果有返回信息 则输入 sudo apt-get install python-tools 2 否则 1.添加软件源地址到apt列表中.输入 ...

  3. for循环打印空心菱形的新方法

    相信大家在学习流程控制的循环结构时,一定都用for循环绘制过菱形和空心菱形吧,我记得我当时写的很麻烦,把一个菱形分为上下两部分,上面2重for循环,下面2重for循环,相信有很多的小伙伴都是这样做的吧 ...

  4. 完美解决windows10磁盘占用100%并出现卡顿、假死无反应

    完美解决windows10磁盘占用100%并出现卡顿.假死无反应 想必大家也跟我一样,自从用win10系统以后经常会出现这种情况:磁盘突然占用100%然后开始出现假死现象,电脑卡住,点击任何软件没反应 ...

  5. JavaFX 集成 Sqlite 和 Hibernate 开发爬虫应用

    目录 [隐藏] 0.1 前言: 0.2 界面 0.3 Maven 环境 0.4 项目结构 0.5 整合 Hibernate 0.5.1 SQLiteDialect.java 数据库方言代码 0.5.2 ...

  6. Unity基础之:UnityAPI的学习

    版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...

  7. Jquery.form异步上传文件常见问题解决

    Jquery.form常用方法我就不多说,主要说一下在使用过程中碰到的问题 1.提示 “xxxx” is not define 或者"xxx" is not a function ...

  8. LeetCode——540. Single Element in a Sorted Array

    题目:Given a sorted array consisting of only integers where every element appears twice except for one ...

  9. AVL树(查找、插入、删除)——C语言

    AVL树 平衡二叉查找树(Self-balancing binary search tree)又被称为AVL树(AVL树是根据它的发明者G. M. Adelson-Velskii和E. M. Land ...

  10. Go开发中的十大常见陷阱[译]

    原文: The Top 10 Most Common Mistakes I've Seen in Go Projects 作者: Teiva Harsanyi 译者: Simon Ma 我在Go开发中 ...