[数据结构]RMQ问题小结
RMQ问题小结
by Wine93 2014.1.14
1.算法简介
RMQ问题可分成以下2种
(1)静态RMQ:ST算法
一旦给定序列确定后就不在更新,只查询区间最大(小)值!这类问题可以用倍增的ST算法进行预处理
预处理:O(nlogn)
查询:O(1)
(2)动态RMQ:线段树
要更新一些值,还有询问
更新:O(logn)
查询:O(logn)
2.相关题目
(1)静态RMQ
1.POJ 3264 Balanced Lineup(一维静态RMQ模板题) http://poj.org/problem?id=3264
题意:给定n(n<=50000)个数字,每次询问[l,r]内的最大值和最小值差
分析:裸的一维RMQ,用ST预处理!
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std; # define N int log2[N];
int a[N],f[N][],g[N][]; //f:max g:min
void initRMQ(int a[],int n)
{
int i,j;
log2[]=;
for(i=;i<N;i++)
log2[i]=log2[i-]+!(i&(i-));
for(i=;i<=n;i++)
f[i][]=g[i][]=a[i];
for(j=;(<<j)<=n;j++)
for(i=;i+(<<j)-<=n;i++)
{
f[i][j]=max(f[i][j-],f[i+(<<j-)][j-]);
g[i][j]=min(g[i][j-],g[i+(<<j-)][j-]);
}
} int getmax(int l,int r)
{
int k=log2[r-l+];
return max(f[l][k],f[r-(<<k)+][k]);
} int getmin(int l,int r)
{
int k=log2[r-l+];
return min(g[l][k],g[r-(<<k)+][k]);
} int main()
{
int i,n,m,x,y;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=;i<=n;i++)
scanf("%d",&a[i]);
initRMQ(a,n);
for(i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
printf("%d\n",getmax(x,y)-getmin(x,y));
}
}
return ;
}
POJ 3264
2.HDU 2888 Check Corners(二维静态RMQ模板题) http://acm.hdu.edu.cn/showproblem.php?pid=2888
题意:给定一个n*m (1<=m,n<=300)的矩阵!每次询问(r1,c1)为左上角,(r2,c2)为右下角的子矩形的最大值。
分析:裸的二维RMQ,用ST预处理即可!
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std; # define N
# define M
int dp[N][N][M][M];
int log2[N];
int a[N][N],n,m,q; void initRMQ()
{
int i,j,k,l;
for(k=;(<<k)<=n&&k<=;k++)
for(l=;(<<l)<=m&&l<=;l++)
for(i=;i+(<<k)-<=n;i++)
for(j=;j+(<<l)-<=m;j++)
{
if(k==&&l==) dp[i][j][k][l]=a[i][j];
else if(k==) dp[i][j][k][l]=max(dp[i][j][k][l-],dp[i][j+(<<l-)][k][l-]);
else if(l==) dp[i][j][k][l]=max(dp[i][j][k-][l],dp[i+(<<k-)][j][k-][l]);
else
{
int a=max(dp[i][j][k-][l-],dp[i][j+(<<l-)][k-][l-]);
int b=max(dp[i+(<<k-)][j][k-][l-],dp[i+(<<k-)][j+(<<l-)][k-][l-]);
dp[i][j][k][l]=max(a,b);
}
}
} int getmax(int x1,int y1,int x2,int y2)
{
int k=log2[x2-x1+];
int l=log2[y2-y1+];
int a=max(dp[x1][y1][k][l],dp[x2-(<<k)+][y1][k][l]);
int b=max(dp[x1][y2-(<<l)+][k][l],dp[x2-(<<k)+][y2-(<<l)+][k][l]);
return max(a,b);
} int main()
{
int i,j,x1,y1,x2,y2;
log2[]=;
for(i=;i<N;i++)
log2[i]=log2[i-]+!((i-)&i);
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=;i<=n;i++)
for(j=;j<=m;j++)
scanf("%d",&a[i][j]);
initRMQ();
scanf("%d",&q);
while(q--)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
int ans=getmax(x1,y1,x2,y2);
int res=max(max(a[x1][y1],a[x1][y2]),max(a[x2][y1],a[x2][y2]));
printf("%d ",ans);
if(res==ans) printf("yes\n");
else printf("no\n");
}
}
return ;
}
HDU 2888
3.LightOJ 1081 Square Queries(二维静态RMQ降维) http://www.lightoj.com/volume_showproblem.php?problem=1081
题意:给定一个n*n(n<=500)的矩阵!每次询问以(x,y)为左上角,边长为l的正方形区域内的最大值
分析:如果用一般的二维RMQ预处理,时间复杂度为n*n*logn*logn(约2000万),会超时!因为查询区域为正方形,我们只要每次都存储正方形就行了!
Max[i][j][k]:以(i,j)为左上角,边长为2^k区域内的最大值,每次倍增把大正方形拆成4个小正方形即可!
# include<map>
# include<set>
# include<cmath>
# include<queue>
# include<stack>
# include<vector>
# include<string>
# include<cstdio>
# include<cstring>
# include<iostream>
# include<algorithm>
# include<functional>
using namespace std; typedef pair<int,int> PII;
# define MOD
# define LL long long
# define pb push_back
# define F first
# define S second
# define N
# define M
int Max[N][N][M],Log2[N];
int a[N][N]; void initLog() //初始化Log2数组
{
int i;
Log2[]=-;
for(i=;i<N;i++)
Log2[i]=Log2[i-]+!(i&i-);
} void initRMQ(int n)
{
int i,j,k,lu,ld,ru,rd;
for(k=;(<<k)<=n;k++)
for(i=;i+(<<k)-<=n;i++)
for(j=;j+(<<k)-<=n;j++)
{
if(k==) Max[i][j][k]=a[i][j];
else
{
lu=Max[i][j][k-]; //左上角
ld=Max[i+(<<k-)][j][k-]; //左下角
ru=Max[i][j+(<<k-)][k-]; //右上角
rd=Max[i+(<<k-)][j+(<<k-)][k-]; //右下角
Max[i][j][k]=max(max(lu,ld),max(ru,rd));
}
}
} int Query(int x,int y,int l)
{
if(l==) return a[x][y]; //注意
int k=Log2[l];
int lu=Max[x][y][k];
int ld=Max[x+l-(<<k)][y][k];
int ru=Max[x][y+l-(<<k)][k];
int rd=Max[x+l-(<<k)][y+l-(<<k)][k];
return max(max(lu,ld),max(ru,rd));
} int main()
{
//freopen("in.txt","r",stdin);
initLog();
int cas,T,i,j,n,m,x,y,l;
scanf("%d",&T);
for(cas=;cas<=T;cas++)
{
scanf("%d%d",&n,&m);
for(i=;i<=n;i++)
for(j=;j<=n;j++)
scanf("%d",&a[i][j]);
initRMQ(n);
printf("Case %d:\n",cas);
while(m--)
{
scanf("%d%d%d",&x,&y,&l);
printf("%d\n",Query(x,y,l));
}
}
return ;
}
Lightoj 1081
4.POJ 3368 Frequent values
题意:给定n(n<=100000)个数,每次询问一个区间内重复数字的最大次数
5.POJ 2452 Sticks Problem
6.HDU 3486 Interviewe
(2)动态RMQ
1.HDU 1754 I Hate It (一维动态RMQ模板题)
2.Uva 11297 Census(二维动态RMQ模板题)
3.HDU 4819 Mosaic (13年长春现场)
4.NBU 2475 Survivors
5.BUAA 724 晴天小猪的神题
[数据结构]RMQ问题小结的更多相关文章
- 数据结构——RMQ
RMQ 今天临放学前终于是学会了RMQ,特此写一篇题解来缅怀 RMQ是一种数据结构,用途是查询区间内最大值或最小值 或者你所要求的任意条件,主要思想是二进制的思想,其中还用到了dp的思想, 是一种非常 ...
- 数据结构(RMQ):POJ 3624 Balanced Lineup
Balanced Lineup Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always li ...
- 数据结构RMQ
RMQ算法介绍 RMQ算法全称为(Range Minimum/Maximum Query)意思是给你一个长度为n的数组A,求出给定区间的最值的下标.当然我们可以采用枚举,但是我们也可以使用线段树来优化 ...
- 数据结构(RMQ):UVAoj 11235 Frequent values
Frequent values You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. I ...
- uva 11235
数据结构 RMQ算法 左右左右 写得有点晕了 ..... /****************************************************************** ...
- RMQ 数据结构
RMQ 常用的数据结构之一 直接上代码 马克好来 是个好板子 #include <stdio.h> #define min(a,b) a<b ? a : b ],d[][]; voi ...
- [数据结构]KMP小结
KMP小结 By Wine93 2013.9 1.学习链接: http://www.matrix67.com/blog/archives/115 2.个人小结 1.KMP在字符串中匹配中起着巨大作 ...
- 【暑假】[实用数据结构]范围最小值问题(RMQ)
范围最小值问题: 提供操作: Query(L,R):计算min{AL ~ AR } Sparse-Table算法: 定义d[i][j]为从i开始长度为2j的一段元素的最小值.所以可以用递推的方法表示. ...
- OpenJudge_cdqz 数据结构版块小结
题目整理 Challenge 0 随机线性存储表-easy Challenge 1 链表数组-easy Challenge 2 可持久化Treap的可持久化运用-hard Challenge 3 ...
随机推荐
- 20145236 《Java程序设计》 第6周学习总结
20145236 <Java程序设计>第6周学习总结 教材学习内容总结 第十章 输入/输出 InputStream与OutputStream 串流设计的概念 Java将输入/输出抽象化为串 ...
- 安装hadoop-2.3.0-cdh5.1.2全过程
工欲善其事,必先利其器,啥都不说,Hadoop下载:http://archive.cloudera.com/cdh5/cdh/5/ 选择好相应版本搞起,在本文讲述的是 围绕hadoop-2.3.0- ...
- Java多线程-新特征-锁(上)
在Java5中,专门提供了锁对象,利用锁可以方便的实现资源的封锁,用来控制对竞争资源并发访问的控制,这些内容主要集中在java.util.concurrent.locks 包下面,里面有三个重要的接口 ...
- .NET 向SQL里写入非Text类型
一般来说,在更新DataTable或是DataSet时,如果不采用SqlParameter,那么当输入的Sql语句出现歧义时,如字符串中含有单引号,程序就会发生错误,并且他人可以轻易地通过拼接Sql语 ...
- 如何在win7下配置IIS?
- SendMessage函数的常用消息及其应用大全
来源:http://www.360doc.com/content/09/0814/10/19147_4907488.shtml,非常全面的解释. 文本框控件通常用于输入和编辑文字.它属于标准 Wind ...
- java版复利计算
这是我修改为java的初定界面,还有很多细节问题还没有解决,希望老师可以给我多点的点评,接下来继续努力,我会把每一次的进步发上来,不断的去锻炼. 1.我所用的开发工具是ecipse 2.所有的语言为j ...
- Arithmetic Progressions
题目大意: 求出满足条件A的等差数列: A:长度为N(N<=25),每个元素都能表示成 两个数p,q的平方和(0<=p,q<=m<=250): 解题过程: 1.处理出所有的能拆 ...
- Ibatis.Net各类的作用说明(三)
一.SqlMapper类 Ibatis中,加载.分析配置以及映射文件是在创建SqlMapper实例的时候进行的,另外对数据库的操作,也是在SqlMapper实例上调用方法来完成.在IBatis外部的程 ...
- move
<span id="span{{$index}}" ng-click="goTab({{$index}})" ng-class="{tabFon ...