【RMQ】区间求最值 SOJ2436 Picture puzzle game
来源:互联网 发布:100元能干什么知乎 编辑:程序博客网 时间:2024/05/16 01:59
RMQ即范围最小值问题(Range Minimum Query,RMQ)
用以解决某段范围内最小值的问题(最大值也可以)
其预处理效率为O(nlogn)查询效率O(1)是一个非常小的常数
RMQ的核心思想在于运用一个二维数组来储存一段长度为2^k范围的最小值
即D[i][j]表示从i开始长度为2^j范围内的最小值
那么我们按照递推的一个思路可以得出
D[i][j]=min(D[i][j-1],D[i+2^(j-1)][j-1])
因为2^j小于n 所以D[][]的大小为D[n][logn] 所以预处理时间为O(nlogn) 空间复杂度也为O(nlogn)
(这里开空间之前建议先写一个小程序预先计算一下logn的最大值 再开空间)
预处理代码如下
<p>inline int MIN(int a,int b){ return a<b?a:b;}</p><p>inline void RMQ_init(){ int i,j; for (j=1;(1<<j)<=n;j++) { for (i=0;i+(1<<j)-1<n;i++) { d[i][j]=MIN(d[i][j-1],d[i+(1<<(j-1))][j-1]); } }}</p>
接下来是查询 我们只需要找到两个区间 使得两个区间覆盖了题目要求的区间即可 因为是求最值所以即便是有重复也没有关系(如果是累加则不允许出现重复)
因此我们现在O(1)的时间复杂度里面需找一个k值 使得k是满足2^k<=R-L+1的最大整数
那么D[L][k]与D[R-2^k+1][k]的较小值就是所要求的
查询代码如下
inline int RMQ(int L,int R){ int k=0; while((1<<(k+1))<=R-L+1) k++; return MIN(d[L][k],d[R-(1<<k)+1][k]);}
这里注意L和R是从下标0开始算的 如果题目给出1开始算下标 那么应该计算RMQ(L-1,R-1)
接下来以SOJ2436 Picture puzzle game为例 试用一下RMQ
问题描述fzk特别擅长拼图游戏,作为科大ACM/ICPC代表队STUDENT的主力成员,他每逢大赛前必然要买一个新的拼图来玩拼图游戏,据说可以攒人品哦!所以迄今为止,fzk已经玩过了好多不同的拼图游戏,我们可以记作 Game1,Game2,Game3,……,GameN。每次他都会记录下来完成拼图的时间,分别是 Time1,Time2,Time3,……,TimeN(单位:分钟)。gzsun十分嫉妒fzk的拼图能力,所以往往故意刁难fzk,问他:“老范,你好年轻啊,hiahia~~。那么从Gamei到Gamej,你完成一个拼图用的最少时间是多少啊?”这下可难坏了fzk,你能不能帮助fzk回答gzsun呢?问题输入首先一个整数t表示测试数据组数(1=<t<=10)。对每组数据,第一行是一个整数N(0<N<=30000),表示总共玩的游戏数。接下来的的一行中是N个整数,对应于Time1…TimeN(都是不超过1000000000的正整数)。然后是一个整数M(0<M<=30000),表示gzsun的询问次数。接下来的M行中每行有两个正整数i,j,1<=i<j<=N。问题输出对每组测试数据中的每次询问(i,j),输出一个正整数t,使得t = min{Timek, i<=k<=j}。样例输入145 3 7 231 42 34 4样例输出232
分析 标准的RMQ模板题 也可以用线段树解决 不过代码量会相对多一些 这里题目给出的n最大为30000 为了防止MLE这里我先写了个小程序计算了一下log30000 大约是17左右
为了拿到best solution的no.1 这里也使用了getchar代替scanf读数 将速度提升到极致
代码如下:
#include <cstring>#include <cstdio>#include <cctype>#include <cmath>const int maxN=30005;int n;int A[maxN];int d[maxN][17];inline bool get(int &t){ bool flag = 0 ; char c; while(!isdigit(c = getchar())&&c!='-') if( c == -1 ) break ; if( c == -1 ) return 0 ; if(c=='-') flag = 1 , t = 0 ; else t = c ^ 48; while(isdigit(c = getchar())) t = (t << 1) + (t << 3) + (c ^ 48) ; if(flag) t = -t ; return 1 ;}inline int MIN(int a,int b){return a<b?a:b;}inline void RMQ_init(){int i,j;for (j=1;(1<<j)<=n;j++){for (i=0;i+(1<<j)-1<n;i++){d[i][j]=MIN(d[i][j-1],d[i+(1<<(j-1))][j-1]);}}}inline int RMQ(int L,int R){int k=0;while((1<<(k+1))<=R-L+1)k++;return MIN(d[L][k],d[R-(1<<k)+1][k]);}int main(){int t,i,m,l,r;get(t);while(t--){get(n);for (i=0;i<n;i++){get(d[i][0]);}RMQ_init();get(m);while(m--){get(l);get(r);printf("%d\n",RMQ(l-1,r-1));}}return 0;}
- 【RMQ】区间求最值 SOJ2436 Picture puzzle game
- RMQ问题(区间求最值)
- RMQ(区间求最值)
- RMQ指定区间求最值
- RMQ区间求最值
- POJ 1224 PICTURE PUZZLE 笔记
- RMQ区间求最值 后缀数组height预处理(区间求最小值)
- poj1651Multiplication Puzzle 区间dp
- POJ1651Multiplication Puzzle(区间dp)
- hdu5456 Matches Puzzle Game
- hihocoder1634-Puzzle Game
- RMQ(区间最大值)
- 区间最值 RMQ
- 区间最小值 RMQ
- 区间最小值 RMQ算法
- RMQ(区间最值)
- RMQ 区间查询
- rmq区间最值
- 加密与解密的简单实现
- C++中delete和delete[]的区别
- 模板
- Linux C 面试题总结
- 小白学c++之同步互斥封装更新
- 【RMQ】区间求最值 SOJ2436 Picture puzzle game
- fopen、fclose、fwrite使用
- 38条PHP编码优化加速技巧
- 【漫画版图表新闻】香港“占中”十问
- 优秀程序员必备的15大技能
- 计算机算法设计与分析(第4版) 王晓东 著 2012.2 笔记(这本书还不错,偏实用、有难度)
- cocos2d_x_08_游戏_FlappyBird
- 日语能力考N1复习1
- @+id/android:list"和"@android:id/list"的写法