【模板】RMQ(计算区间最值)
①一维RMQ
(1) dp[i,j] 表示从第i个数起连续2j个数中的(最大值min、最小值max、最大公约数gcd……),通过更改下列代码中的红色函数即可实现。
(2) b数组放置所需查询的数列。
- const int MAX=;
- int dp[MAX][];
- int mm[MAX];
- void initrmq(int n,int b[])
- {
- mm[]=-;
- for(int i=;i<=n;i++)
- {
- mm[i]=((i&(i-))==)?mm[i-]+:mm[i-];
- dp[i][]=b[i];
- }
- for(int j=;j<=mm[n];j++)
- for(int i=;i+(<<j)-<=n;i++)
- dp[i][j]=max(dp[i][j-],dp[i+(<<(j-))][j-]);
- }
- ll rmq(int x,int y)
- {
- int k=mm[y-x+];
- return max(dp[x][k],dp[y-(<<k)+][k]);
- }
②二维RMQ
给定一个n*m矩阵,每次询问左上角(r1,c1)到右下角(r2,c2)的子矩形中的(最大值min、最小值max、最大公约数gcd……)并输出。如果每次所询问的四个角有符合条件的数,输出yes,否则输出no。
- #include<algorithm>
- #include<iostream>
- #include<cstdio>
- #include<cmath>
- #include<map>
- using namespace std;
- typedef long long ll;
- const int MAX=;
- int val[MAX][MAX];
- int dp[MAX][MAX][][];//最大值
- int mm[MAX];
- void initRMQ(int n,int m)//m*n的矩阵
- {
- for(int i=;i<=n;i++)
- for(int j=;j<=m;j++)
- dp[i][j][][]=val[i][j];
- for(int ii=;ii<=mm[n];ii++)
- for(int jj=;jj<=mm[m];jj++)
- if(ii+jj)
- for(int i=;i+(<<ii)-<=n;i++)
- for(int j=;j+(<<jj)-<=m;j++)
- if(ii)dp[i][j][ii][jj]=max(dp[i][j][ii-][jj],dp[i+(<<(ii-))][j][ii-][jj]);
- else dp[i][j][ii][jj]=max(dp[i][j][ii][jj-],dp[i][j+(<<(jj-))][ii][jj-]);
- }
- int rmq(int x1,int y1,int x2,int y2)//所查询矩形区间内的最大值 左上角(x1,y1) -> 右上角(x2,y2)
- {
- int k1=mm[x2-x1+];
- int k2=mm[y2-y1+];
- x2=x2-(<<k1)+;
- y2=y2-(<<k2)+;
- return max(max(dp[x1][y1][k1][k2],dp[x1][y2][k1][k2]),max(dp[x2][y1][k1][k2],dp[x2][y2][k1][k2]));
- }
- int main()
- {
- mm[]=-;
- for(int i=;i<=MAX;i++)
- mm[i]=((i&(i-))==)?mm[i-]+:mm[i-];
- int n,m,Q;
- int r1,c1,r2,c2;
- while(scanf("%d%d",&n,&m)==)
- {
- for(int i=;i<=n;i++)
- for(int j=;j<=m;j++)
- scanf("%d",&val[i][j]);
- initRMQ(n,m);
- scanf("%d",&Q);
- while(Q--)
- {
- scanf("%d%d%d%d",&r1,&c1,&r2,&c2);//左上角(r1,c1) -> 右上角(r2,c2)
- if(r1>r2)swap(r1,r2);
- if(c1>c2)swap(c1,c2);
- int tmp=rmq(r1,c1,r2,c2);
- printf("%d ",tmp);
- if(tmp==val[r1][c1]||tmp==val[r1][c2]||tmp==val[r2][c1]||tmp==val[r2][c2])
- printf("yes\n");
- else printf("no\n");
- }
- }
- return ;
- }
③二维RMQ降维
给定一个n*n(n<=500)的矩阵(即是正方形),每次询问以(x,y)为左上角,边长为s的正方形区域内的最大值。
dp[i][j][k]:以(i,j)为左上角,边长为2^k的正方形区域内的最大值。
- #include<algorithm>
- #include<iostream>
- #include<cstdio>
- #include<cmath>
- using namespace std;
- typedef long long ll;
- const int MAX=;
- int dp[MAX][MAX][],mm[MAX],val[MAX][MAX];
- void initrmq(int n)
- {
- int lt,lb,rt,rb;
- for(int k=;k<=mm[n];k++)
- for(int i=;i+(<<k)-<=n;i++)
- for(int j=;j+(<<k)-<=n;j++)
- if(k==)
- dp[i][j][k]=val[i][j];
- else
- {
- lt=dp[i][j][k-]; //左上角
- lb=dp[i+(<<k-)][j][k-]; //左下角
- rt=dp[i][j+(<<k-)][k-]; //右上角
- rb=dp[i+(<<k-)][j+(<<k-)][k-];//右下角
- dp[i][j][k]=max(max(lt,lb),max(rt,rb));
- }
- }
- int rmq(int x,int y,int s)
- {
- if(s==)return val[x][y];
- int k=mm[s];
- int lt=dp[x][y][k];
- int lb=dp[x+s-(<<k)][y][k];
- int rt=dp[x][y+s-(<<k)][k];
- int rb=dp[x+s-(<<k)][y+s-(<<k)][k];
- return max(max(lt,lb),max(rt,rb));
- }
- int main()
- {
- int i,j,k,T;
- mm[]=-;
- for(i=;i<=MAX;i++)
- mm[i]=((i&(i-))==)?mm[i-]+:mm[i-];
- scanf("%d",&T);
- for(int cas=;cas<=T;cas++)
- {
- int n,q;
- scanf("%d%d",&n,&q);
- for(i=;i<=n;i++)
- for(j=;j<=n;j++)
- scanf("%d",&val[i][j]);
- initrmq(n);
- printf("Case %d:\n",cas);
- while(q--)
- {
- int x,y,s;
- scanf("%d%d%d",&x,&y,&s);
- printf("%d\n",rmq(x,y,s));
- }
- }
- return ;
- }
【模板】RMQ(计算区间最值)的更多相关文章
- ST表 求 RMQ(区间最值)
RMQ即Range Minimum/Maximun Query,中文意思:查询一个区间的最小值/最大值 比如有这样一个数组:A{3 2 4 5 6 8 1 2 9 7},然后问你若干问题: 数组A下标 ...
- 【RMQ】 区间最值查询详解
1. 概述 RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A ...
- hdu3183 rmq求区间最值的下标
两个月前做的题,以后可以看看,是rmq关于求区间最值的下标 /* hdu3183 终点 给一个整数,可以删除m位,留下的数字形成一个新的整数 rmq 取n-m个数,使形成的数最小 */ #includ ...
- 基于稀疏表(Sparse Table)的RMQ(区间最值问题)
在RMQ的其他实现方法中,有一种叫做ST的算法比较常见. [构建] dp[i][j]表示的是从i起连续的2j个数xi,xi+1,xi+2,...xi+2j-1( 区间为[i,i+2j-1] )的最值. ...
- 【模板】 RMQ求区间最值
RMQ RMQ简单来说就是求区间的最大值(最小值) 核心算法:动态规划 RMQ(以下以求最大值为例) F[i,j]表示 从 i 开始 到i+2j -1这个区间中的最大值 状态转移方程 F[i,j]=m ...
- RMQ求区间最值 nlog(n)
转载于:http://blog.csdn.net/xuzengqiang/article/details/7350465 RMQ算法全称为(Range Minimum/Maximum Query)意思 ...
- RMQ算法区间最值
问题类型:是多次询问一个大区间里子区间的最值问题 dp + 位运算的思想处理 rmax[i][j]表示从i开始到i + 2^j - 1的区间里的最大值dp[i][j] ==== (i,i + 2^j ...
- HDU 5919 - Sequence II (2016CCPC长春) 主席树 (区间第K小+区间不同值个数)
HDU 5919 题意: 动态处理一个序列的区间问题,对于一个给定序列,每次输入区间的左端点和右端点,输出这个区间中:每个数字第一次出现的位子留下, 输出这些位子中最中间的那个,就是(len+1)/2 ...
- RMQ(模板 ST 区间最值,频繁的间隔时间)
PS: 介绍:http://blog.csdn.net/liang5630/article/details/7917702 RMQ算法.是一个高速求区间最值的离线算法,预处理时间复杂度O(n*log( ...
随机推荐
- 转动的八卦图纯css实现
这类的东西网上一搜就是大把的,看着比较空旷的博客,所以自己也来写一个. <!DOCTYPE html> <html> <head> <meta chars ...
- 1-3 Sass 语法、编译、调试
Sass 语法格式 这里说的 Sass 语法是 Sass 的最初语法格式,他是通过 tab 键控制缩进的一种语法规则,而且这种缩进要求非常严格.另外其不带有任何的分号和大括号.常常把这种格式称为 Sa ...
- Django—XSS及CSRF
一.XSS 跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS.恶意攻击者往W ...
- apk下载安装,存储的位置,路径
PackageInstaller 原理简述 应用安装是智能机的主要特点,即用户可以把各种应用(如游戏等)安装到手机上,并可以对其进行卸载等管理操作.APK是Android Package的缩写,即An ...
- Hush Framework框架配置(转)
在写这篇文章的时候,楼主已经饿的不行了,因为我从3点开始就在折腾Hush Framework,走了很多弯路,打铁要趁热,先把基本的过程记录下来,留待以后翻阅,同时记录其中容易走弯路的地方,特别是对于一 ...
- qwewq
- ES6/ES2015常用知识点和概念
越来越多的开源库开始使用ES2015来构建代码了,大家知道ES6=ES2015,ES6在2015年被ECMAScript标准化组织approve,各大浏览器厂商要完全支持ES6的强大功能还须一些时日, ...
- SQLServer 2008 新增T-SQL 简写语法
1.定义变量时可以直接赋值 DECLARE @Id int = 5 2.Insert 语句可以一次插入多行数据 INSERT INTO StateList VALUES(@Id, 'WA'), (@I ...
- DEV控件之ChartControl用法 z
一.总体概述 这个控件包含3层,最外面的chartControl层.中间的XYDiagram层.最里面的Series层.功能非常强大,但同时使用起来也相对复杂,需要各个层之间相互协调设置才能达到自己想 ...
- 运维不仅仅是懂Linux就行,还需要知道这些……
运维不仅仅是懂Linux就行,因为还有一大部分的Windows运维,最近看一个报道说,windows的服务器占了47.71%.嗯,向windows运维人员致敬.当然我们这篇文章不是说运维除了懂Linu ...