- 浏览: 543713 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (231)
- 一个操作系统的实现 (20)
- 汇编(NASM) (12)
- Linux编程 (11)
- 项目管理 (4)
- 计算机网络 (8)
- 设计模式(抽象&封装) (17)
- 数据结构和算法 (32)
- java基础 (6)
- UML细节 (2)
- C/C++ (31)
- Windows (2)
- 乱七八糟 (13)
- MyLaB (6)
- 系统程序员-成长计划 (8)
- POJ部分题目 (10)
- 数学 (6)
- 分布式 & 云计算 (2)
- python (13)
- 面试 (1)
- 链接、装载与库 (11)
- java并行编程 (3)
- 数据库 (0)
- 体系结构 (3)
- C++ template / STL (4)
- Linux环境和脚本 (6)
最新评论
-
chuanwang66:
默默水塘 写道typedef void(*Fun)(void) ...
C++虚函数表(转) -
默默水塘:
typedef void(*Fun)(void);
C++虚函数表(转) -
lishaoqingmn:
写的很好,例子简单明了,将观察者模式都表达了出来。
这里是ja ...
观察者模式——Observer
一、RMQ问题描述 和 几种解题思路
RMQ问题 (Range Minimum/Maximum Query),首先给出一个序列,然后不断询问某个区间内的最大值和最小值。显然,我们在回答所有询问之前,需要根据序列进行一定的预处理。
(1)最笨的算法显然是朴素的直接查询 ,回答每个问题是O(n)的。
(2)一种算法是采用线段树
,即在线段树的每个节点保存该区间的最大值与最小值,O(n)的预处理时间(需要自底向上构建),可以O(logn)地回答每个问题。关于这种解法,见我线段树专题中炮兵阵地那道题即可:)
(3)另一种算法就是神奇的ST算法(Sparse Table)
,ST算法记录了所有长度为2^f的区间的最值
。以求最大值为例,设v[n][f]表示[
n,n+2^f)
这个区间内的最大值,那么在询问到[a,b)区间的最大值时答案就是max(v[a][f],v[b-2^f][f]),其中f是满足2^f<=b-a的最大的f。至于那张稀疏表,可以用递推的方法在O(nlogn)(也就是表的元素数)的时间内构建。也就是说v[n][f]=max(v[n][f-1],v[n+2^(f-1)][f-1])。
下面是我写的C++代码,有待改进:
#include <iostream> #include <ctime> #include <cmath> #include <cstdlib> using namespace std; /* ST(Sparse Table): find max/min number in [A,B] within O(nlogn), n=B-A 构造:v[ a~b ][ 0~ceil( log(B-A)) ] init: v[i][0]=d[i], i∈[A,B] , 注意:v[i][0]对应前闭后开区间[i, i+2^0) recurse: v[i][f]=min{ v[i][f-1], v[i-2^(f-1)][f-1] } --------------------------------------------------------------------------------------------- prob: find max/min in [a,b)∈ [A,B] soln: max{ v[a][f], v[b-2^f][f] } <== a+2^f>=b-2^f <== 2^(f+1)>=b-a, f=0↑的首个满足条件的值 */ //查询d[A...B]范围内数组的最值 const int MAX=101; int cnt=30; //随机交换次数 const int INF=9999; int A=2; int B=30; int data[MAX]; //ST算法DS: v[][] int v[MAX][MAX]; int minV(int i, int j){ return (i)<(j)?(i):(j); } //给d[]赋予随机数 void initData(){ for(int i=0;i<MAX;i++){ data[i]=i; } //随机交换 srand(time(0)); while(cnt-->0){ int i= A + (rand()%(B-A)); int j= A + (rand()%(B-A)); //cout<<"swap("<<i<<", "<<j<<")"<<endl; if(i!=j){ int tmp=data[i]; data[i]=data[j]; data[j]=tmp; } } } void showData(){ for(int i=A;i<=B;i++){ cout<<data[i]<<"\t"; } cout<<endl; } //构造ST算法DS: v[] void initV(){ //init: for(int i=0;i<MAX;i++){ for(int j=0;j<MAX;j++){ v[i][j]=INF; } } for(int i=A;i<=B;i++){ v[i][0]=data[i]; //当求min时,其余的v[i][0]必须预设为很大的值 } //DP iteration: for(int i=1;i<=ceil( log(B-A)/log(2) );i++){ for(int j=A;j<=B;j++){ v[j][i]=minV( v[j][i-1], v[j+(int)pow((double)2,(double)(i-1))][i-1] ); /* cout<<"v["<<j<<"]["<<i<<"]="<<v[j][i]<<"= minV("; cout<<"v["<<j<<"]["<<i-1<<"]="<<v[j][i-1]<<", \t"; cout<<"v["<<j+(int)pow((double)2,(double)(i-1))<<"]["<<i-1<<"]="<<v[j+(int)pow((double)2,(double)(i-1))][i-1]<<")"<<endl; */ } } } void showV(){ for(int i=0;i<=ceil( log(B-A)/log(2) );i++){ for(int j=A;j<=B;j++){ cout<<"v["<<j<<"]["<<i<<"]="<<v[j][i]<<"\t"; } cout<<endl<<endl; } cout<<endl; } int query(int a,int b){ int f=0; while( (int)pow((double)2,(double)(f+1)) < (b-a) ){ f++; } return minV( v[a][f], v[b-(int)pow((double)2,(double)f)][f] ); } int main() { initData(); showData(); initV(); //showV(); int queries; cout<<"# of queries:"; cin>>queries; while(queries-->0){ int a,b; cout<<"[a :"; cin>>a; cout<<"b) :"; cin>>b; cout<<"res : "<<query(a,b)<<endl<<endl; } system("pause"); return 0; }
另外,RMQ问题与LCA(Least Common Ancestors,最近公共祖先)问题可以互相转化。LCA问题有一个经典的离线算法Tarjan算法,稍后我将会介绍。
二、ST算法
POJ 3264 Balanced Lineup ==> http://poj.org/problem?id=3264
代码参考这个大牛的: http://www.cnblogs.com/mjc467621163/archive/2011/08/24/2152133.html
//poj 3264 Balanced Lineup #include<iostream> //ST算法,即(Sparse_Table ,稀疏表),可以在O(nlogn)的预处理以后,实现O(1)的查询效率 #include <cmath> using namespace std; const int max_n=50005; int arr[max_n],n,t,l,r; //原数列arr从下标1开始 int rmq_m[max_n][16],rmq_n[max_n][16]; //16>=log2(50000)==15.609640474436811739351597147447 //rmq_m[i][j],rmq_n[i][j]分别表示原数列arr[i, i+2^j - 1]区间中的最大值和最小值,区间长度为2^j void rmq_init() //预处理,采用DP { int i,j; //1. DP-INIT: 长度为2^0==1的区间的最值就是单点上的值 for(i=1;i<=n;++i) rmq_m[i][0]=rmq_n[i][0]=arr[i]; //2. DP-ITERATION: rmq[i][j]=max{ rmq[i][j-1], rmq[i+2^(j-1)][j-1] } // 可见 rmq[*][j]=max{ rmq[$][j-1], rmq[#][j-1] } ,因此 j 放在循环外层,且顺序循环 for(j=1;j<=log(n+0.0)/log(2.0);++j) //j表示区间长度为2^j,区间范围[i, i+2^j - 1],小于等于n,所以 j<=log(n+0.0)/log(2.0) { for(i=1;i+(1<<j)-1<=n;++i) //因为rmq_m[i][j]表示arr[i, i+2^j - 1]的最大值,所以 i+2^j - 1 <= n { rmq_m[i][j]=max(rmq_m[i][j-1],rmq_m[i+(1<<(j-1))][j-1]); rmq_n[i][j]=min(rmq_n[i][j-1],rmq_n[i+(1<<(j-1))][j-1]); } } } //DP的初值:rmq_m[i][0]其实就等于arr[i]; 状态转移方程:rmq_m[i][j]=max(rmq_m[i][j-1],rmq_n[i+2^(j-1)][j-1]) //采用自底向上的算法递推地给出所有符合条件的rmq_m[i][j]的值 int rmq(int a,int b) //查询 { /* 要使得[a,b]的max = max{ [a, a+2^m]的max, [b-2^m+1, m]的max } 需要 m 大于一定值: a+2^m >= b-2^m+1 <==> m >= log(b-a+1)/log(2) - 1 <==> m 至少是 floor[ log(b-a+1)/log(2) ] */ int m=log(b-a+1.0)/log(2.0); int x=max(rmq_m[a][m],rmq_m[b-(1<<m)+1][m]); //区间[a,b]最大值 int y=min(rmq_n[a][m],rmq_n[b-(1<<m)+1][m]); return x-y; } //查询从a到b这一段的最大(小)值, 那么我们先求出一个最大的整数m, 使得m满足2^m <= (b - a + 1). //于是我们就可以把[a, b]分成两个长度为2^m的区间: [a, a+2^m -1], [b-2^m +1, b]; (有部分重叠,b-2^m +1 <= a+2^m -1) //而rmq_m[a][m]为[a, a+2^m-1]的最大值, rmq_m[b-2^m +1][m]为[b-2^m +1, b]的最大值 int main() { scanf("%d%d",&n,&t); for(int i=1;i<=n;++i) scanf("%d",arr+i); rmq_init(); while(t--) { scanf("%d%d",&l,&r); printf("%d\n",rmq(l,r)); } return 0; }
参考:
问题概述和主要思路:
http://cuitianyi.com/blog/rmq%E9%97%AE%E9%A2%98/
发表评论
-
快排备忘
2013-10-26 11:27 583http://hi.baidu.com/pluto455988 ... -
LRU简单实现C++
2013-10-17 10:52 4027页面置换算法: 在地址映射过程中,若在页面中发现所要访问的页 ... -
二叉树相关
2013-10-04 17:40 727本节主要是为了写二叉树类型题目练手的代码,重点培养运用“指针 ... -
双指针策略(《编程之美》3.5 最短摘要生成)
2013-03-26 15:17 2252本文源自《编程之美》3.5 最短摘要生成一课。 ... -
K-MEDOIDS聚类算法
2012-12-04 21:18 2001k-medoids聚类算法 (wiki上讲得很清楚啊:) ) ... -
搜索(三)——回溯
2012-11-23 15:23 1055一、回溯 和 深度搜索 ... -
哈希Hash
2012-11-21 14:42 1008要点一:哈希表长度 的确定是个两难的问题:太短则容 ... -
状态压缩DP
2012-11-14 20:27 759引例、 例1、 例2、 例3、 ... -
模拟退火
2012-10-28 16:34 1233引用:http://www.cnblogs.com/heaad ... -
计算几何(一)——基础算法
2012-07-12 21:07 1932待续 《计算几何资料》为提纲 1. (1) 有向线段 ... -
计算几何(二)——平面最近点对
2012-07-12 10:54 922参考资料: 为何这个问题采用分治法 http://blog ... -
气泡滚大——剔除线性数据中的杂质
2012-06-18 09:43 972这是一道Java的面试题,但是我总结了除了一种自称为“ ... -
深入理解二分查找(二、二分答案)
2012-04-29 16:24 7220二分答案 如果已知候选答案的范围[min,max ... -
P问题、NP问题和NPC问题
2012-04-25 16:36 1081这篇文章转自这里 ... -
后缀数组
2012-04-16 09:49 1539一、后缀数组 及其对应的名次数组 举例:S=&quo ... -
大整数运算(部分转载)
2012-04-12 21:36 1204待补充:“浮点数高精度运算” 参见这里==> ... -
单向链表相关
2012-04-10 16:42 995单向链表是微软笔试常考的,参考这里:http://www.c ... -
关键路径(AOE)
2012-04-10 08:05 1684前面这段话是引用别人的,后面代码是自己写的,有待完善: ... -
搜索(二)——双向BFS
2012-03-24 17:18 3037参考这篇文章,以下前 ... -
搜索(一)——剪枝
2012-03-24 11:46 1571参考文档:《搜索方法 ...
相关推荐
区间最值查询(Range Minimum/Maximum Query,简称RMQ)是数据结构和算法领域中一个经典的问题。在处理大规模数据时,我们往往需要快速查询一个序列或者数组在某个连续子区间内的最大值或最小值,而RMQ算法就是为此...
Structure rmq(range minimum or maximum query) help to find minimum or maximum on segment l and r O(log(l-r+1)) and update O(logN)
RMQ(Range Minimum/Maximum Query,区间最值查询)和LCA(Least Common Ancestor,最近公共祖先)是数据结构和算法中的重要概念,它们在解决实际问题中有着广泛的应用。下面将详细介绍这两种算法的基本概念、经典...
### RMQ(Range Minimum/Maximum Query)详解 #### 引言 在计算机科学与算法设计领域,RMQ问题,即范围最小/最大查询问题,是一个经典的动态规划与数据结构问题。它涉及到对一段连续的数据进行快速查询,找到该区间...
RMQ(Range Minimum/Maximum Query)问题是在一个给定的数组中寻找某个区间内的最大值或最小值。这种问题在数据结构和算法中非常常见,特别是在处理动态查询时。暴力解决方法是对于每次询问,遍历指定的区间,时间...
RMQ(Range Minimum/Maximum Query)即区间最小/最大查询问题,旨在对一个序列中任意指定区间的最小值或最大值进行查询。一些算法,比如线段树,可以用来解决这个问题。 LCA(Least Common Ancestor)是查找最近...
ST表是一种数据结构,用于解决RMQ(Range Minimum/Maximum Query)问题,即区间最值查询。RMQ问题是指对于长度为n的数列A,回答若干询问RMQ(A, i, j)(i, j ),返回数列A中下标在i, j之间的最小/大值。 例如,给...
RMQ(Range Minimum/Maximum Query)问题是一种常见的数据结构与算法问题,其核心任务是在一个给定的数组中快速找到指定区间内的最小值或最大值。这类问题在计算机科学和算法竞赛中十分常见,并且具有广泛的应用场景...
2. RMQ(Range Minimum/Maximum Query)数据结构,用于解决区间最值查询问题。该数据结构可以预处理数组,在O(1)时间复杂度内回答关于区间最值的问题。代码中实现了`RMQ(int[] vs)`构造函数用于初始化数据结构,以及...
RMQ问题(Range Minimum/Maximum Query,区间最小/大值查询)是计算机科学中一个非常基础且重要的问题。其核心在于快速找到数组中某个指定区间内的最大或最小值。在实际应用中,例如在图像处理、生物信息学以及...
RMQ问题,全称为Range Minimum Query / Range Maximum Query(区间最小值查询/区间最大值查询),指的是在一个给定的序列A中,对任意指定的区间[i, j](其中1 ≤ i ≤ j ≤ n,n为序列A的长度),找到该区间内元素的...
RMQ,全称为Range Maximum (Minimum) Query,是信息学竞赛中常见的算法问题,主要用于解决在数组中查询连续子区间最大值或最小值的问题。它通常出现在需要频繁进行区间最值查询的题目中,能够有效地减少计算量,提高...
RMQ(Range Maximum/Minimum Query)是指在一个固定数组中查询特定区间内的最大值或最小值的问题。这类问题在算法竞赛中非常常见,特别是在那些需要频繁进行区间查询的任务中。 #### 二、RMQ的原理与算法实现 RMQ...
- RMQ(Range Minimum/Maximum Query)问题的不同解决算法。 - LCA(Lowest Common Ancestor)问题的离线算法。 - 带权值的并查集。 - 快速排序、堆栈、区间最大频率。 - 归并排序、二分查找以及各种字符串处理算法...
- **定义**:区间最值查询(Range Minimum/Maximum Query)是指在一个数组中快速找到指定区间的最小值或最大值。 - **倍增思想**:通过预先计算区间长度为\(2^k\)的所有子区间的最小值/最大值,利用这些信息快速...
- RMQ(Range Minimum/Maximum Query):求区间最小/大值的算法。 - Treap、划分树:平衡二叉搜索树的变形,用于区间查询。 - 树链剖分:用于处理树上路径查询问题。 - Splay、DLX(舞蹈链):特殊的平衡二叉...
- 树状数组、后缀数组、TRIE树(K叉树和左儿子右兄弟模型)、RMQ(Range Minimum/Maximum Query)问题的解决策略。 - LCA(Lowest Common Ancestor)问题的不同解法。 - 带权值的并查集、快速排序、大数运算、最长...
此外,文件内容还提及了RMQ(Range Minimum/Maximum Query)和LCA(Least Common Ancestor)问题。RMQ问题关注于在数组或者序列中寻找最小(或最大)元素的问题,而LCA问题则是在树结构中寻找两个节点的最低公共祖先...
2.3 **区间极值问题(RMQ,Range Minimum/Maximum Query)**:在一个数组中,查询某个连续子数组内的最小或最大值。倍增算法通过构建ST表(Sparse Table)预先计算每个2的幂次子数组的极值,然后快速获取任意区间内...
ZKW单点修改指的是在线段树上进行单个元素的修改,RMQ(Range Minimum/Maximum Query)则是在一个区间内查找最小/大值,区间加+赋值是指对某个区间的所有元素进行加法操作或赋新值。 6. **Splay树**:自旋平衡二叉...