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问题小结的更多相关文章

  1. 数据结构——RMQ

    RMQ 今天临放学前终于是学会了RMQ,特此写一篇题解来缅怀 RMQ是一种数据结构,用途是查询区间内最大值或最小值 或者你所要求的任意条件,主要思想是二进制的思想,其中还用到了dp的思想, 是一种非常 ...

  2. 数据结构(RMQ):POJ 3624 Balanced Lineup

    Balanced Lineup   Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always li ...

  3. 数据结构RMQ

    RMQ算法介绍 RMQ算法全称为(Range Minimum/Maximum Query)意思是给你一个长度为n的数组A,求出给定区间的最值的下标.当然我们可以采用枚举,但是我们也可以使用线段树来优化 ...

  4. 数据结构(RMQ):UVAoj 11235 Frequent values

    Frequent values You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. I ...

  5. uva 11235

    数据结构 RMQ算法   左右左右   写得有点晕了 ..... /****************************************************************** ...

  6. RMQ 数据结构

    RMQ 常用的数据结构之一 直接上代码 马克好来 是个好板子 #include <stdio.h> #define min(a,b) a<b ? a : b ],d[][]; voi ...

  7. [数据结构]KMP小结

    KMP小结   By Wine93 2013.9 1.学习链接: http://www.matrix67.com/blog/archives/115 2.个人小结 1.KMP在字符串中匹配中起着巨大作 ...

  8. 【暑假】[实用数据结构]范围最小值问题(RMQ)

    范围最小值问题: 提供操作: Query(L,R):计算min{AL ~ AR } Sparse-Table算法: 定义d[i][j]为从i开始长度为2j的一段元素的最小值.所以可以用递推的方法表示. ...

  9. OpenJudge_cdqz 数据结构版块小结

    题目整理 Challenge 0  随机线性存储表-easy Challenge 1  链表数组-easy Challenge 2  可持久化Treap的可持久化运用-hard Challenge 3 ...

随机推荐

  1. mysql 游标取值为空的问题

    DELIMITER $$ DROP PROCEDURE IF EXISTS updatePic $$ CREATE PROCEDURE updatePic() BEGIN DECLARE cover_ ...

  2. Ext grid checkbox 分页 翻页 勾选 问题

    timeArray = new Array(); //临时数组变量 var timeStatusBar = new Ext.ux.StatusBar({ id: 'statusbar', defaul ...

  3. Htmlhelper—CheckBox自动生成两个input

    前言 在之前的一篇文章中小猪分享了Htmlhelper的用法.其中有意思的一个就是Checkbox,有必要单独拿出来讲一讲. Htmlhelper—CheckBox 细心的读者一定发现了当使用类似语法 ...

  4. SQL is null函数

    Sql ISNULL() 函数 使用指定的替换值替换 NULL.   语法 ISNULL ( check_expression , replacement_value )   参数 check_exp ...

  5. 二分搜索法(转载自vanezkw)

    二分查找算法java实现 今天看了一下JDK里面的二分法是实现,觉得有点小问题.二分法的实现有多种今天就给大家分享两种.一种是递归方式的,一种是非递归方式的.先来看看一些基础的东西. 1.算法概念. ...

  6. POJ 1860 Currency Exchange 最短路 难度:0

    http://poj.org/problem?id=1860 #include <cstdio> //#include <queue> //#include <deque ...

  7. 用ant进行编译和打包(java)

    ant是目前java环境下最好用的打包部署工具,其采用xml的格式进行编写,功能非常强大.现介绍一下如何手工使用ant进行java程序的编译打包.一.安装ant1.下载并安装ant.到官方主页http ...

  8. redis学习(一)

    一.redis简介 Redis是基于内存.可持久化的日志型.key-value高性能存储系统.关键字(Keys)是用来标识数据块.值(Values)是关联于关键字的实际值,可以是任何东西.有时候你会存 ...

  9. DB2配置信息查看及其更新命令

    获取DB2配置信息 db2 get dbm cfg 更新DB2链接配置信息 db2 update dbm cfg using authentication server db2stop db2star ...

  10. [windows驱动]windows8.1驱动调试前戏

    人们都说在干正事之前,得先做足前戏才会爽,我一直很认同这个观点,下面我来总结下进行windows8.1的WDK调试所要做的准备工作. 软件安装: 1.VS2013. 2.WDK8.1 3.Window ...