RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就是说。RMQ问题是指求区间最值的问题。

Time Limit: 5000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u

Submit Status

Description

For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple, he will take a contiguous range
of cows from the milking lineup to play the game. However, for all the cows to have fun they should not differ too much in height.

Farmer John has made a list of Q (1 ≤ Q ≤ 200,000) potential groups of cows and their heights (1 ≤ height ≤ 1,000,000). For each group, he wants your help to determine the difference in height between the shortest and the tallest
cow in the group.

Input

Line 1: Two space-separated integers, N and Q

Lines 2.. N+1: Line i+1 contains a single integer that is the height of cow i

Lines N+2.. NQ+1: Two integers A and B (1 ≤ A ≤ B ≤ N), representing the range of cows from A to B inclusive.

Output

Lines 1.. Q: Each line contains a single integer that is a response to a reply and indicates the difference in height between the tallest and shortest cow in the range.

Sample Input

6 3
1
7
3
4
2
5
1 5
4 6
2 2

Sample Output

6
3
0

1.朴素(遍历): 复杂度O(n)-O(qn)。

2.线段树 :复杂度O(n)-O(qlogn)。

3.ST(Sparse Table)算法 :O(nlogn)-O(q)

说下ST算法,由于每一个查询仅仅有O(1)。在处理大量查询的时候有优势。

<1>.预处理(动态规划DP)

对A[i]数列,F[i][j] 表示从第i个数起连续2^j 中的最大值(DP的状态),能够看到,F[i][0] 表示的是A[i](DP的初始值)。

最后。状态转移方程是

F[i][j]=max(F[i][j-1],F[i+2^(j-1)][j-1])

<2>查询

若查询区间为(a。b),区间长度为b-a+1,取k=log2(b-a+1),则Max(a。b)=max(F[a][k]。F[b-2^k+1][k])。

1.ST算法

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
using namespace std; const int MAXN = 50050; int mins[MAXN][20];
int maxs[MAXN][20]; void RMQ(int n)
{
for (int j = 1; (1 << j) <= n;j++)
for (int i = 1; i + (1 << j) - 1 <= n; i++)
{
int p = (1 << (j - 1));
mins[i][j] = min(mins[i][j - 1], mins[i + p][j - 1]);
maxs[i][j] = max(maxs[i][j - 1], maxs[i + p][j - 1]);
}
} int queryMin(int l, int r)
{
int k = log((double)(r - l + 1))/log(2.0);
return min(mins[l][k], mins[r - (1 << k) + 1][k]);
} int queryMax(int l, int r)
{
int k = log((double)(r - l + 1))/log(2.0);
return max(maxs[l][k], maxs[r - (1 << k) + 1][k]);
} int main()
{
int n, q;
scanf("%d%d", &n, &q);
int num;
for (int i = 1; i <= n; i++)
{
scanf("%d", &num);
maxs[i][0] = mins[i][0] = num;
}
RMQ(n);
int a, b;
int ans;
for (int i = 0; i < q; i++)
{
scanf("%d%d", &a, &b);
ans= queryMax(a, b) - queryMin(a, b);
printf("%d\n", ans);
}
}

2.线段树

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b) using namespace std; const int MAXN = 50050; int num[MAXN]; struct node
{
int r;
int l;
int Max;
int Min;
}tree[3*MAXN]; void build(int l, int r, int i)
{
tree[i].l = l; tree[i].r = r;
if (l == r)
{
tree[i].Max = tree[i].Min = num[l];
return;
}
int m = (l + r) >> 1, ls = i << 1, rs = ls + 1;
build(l, m, ls);
build(m + 1, r, rs);
tree[i].Max = max(tree[rs].Max, tree[ls].Max);
tree[i].Min = min(tree[rs].Min, tree[ls].Min);
} int queryMax(int l, int r, int i)
{
if (tree[i].l == l&&tree[i].r == r)
return tree[i].Max;
int m = (tree[i].l + tree[i].r) >> 1, ls = i << 1, rs = ls + 1;
if (r <= m) return queryMax(l, r, ls);
else if (l > m) return queryMax(l, r, rs);
else return max(queryMax(l, m, ls), queryMax(m + 1, r, rs));
} int queryMin(int l, int r, int i)
{
if (tree[i].l == l&&tree[i].r == r)
return tree[i].Min;
int m = (tree[i].l + tree[i].r) >> 1, ls = i << 1, rs = ls + 1;
if (r <= m) return queryMin(l, r, ls);
else if (l > m) return queryMin(l, r, rs);
else return min(queryMin(l, m, ls), queryMin(m + 1, r, rs));
} int main()
{
int n, q;
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; i++)
scanf("%d", &num[i]);
build(1, n, 1);
int a, b;
int ans;
for (int i = 0; i < q; i++)
{
scanf("%d%d", &a, &b);
ans = queryMax(a, b, 1) - queryMin(a, b, 1);
printf("%d\n", ans);
}
}

參考了http://blog.csdn.net/niushuai666/article/details/6624672/

POJ - 3264 Balanced Lineup (RMQ问题求区间最值)的更多相关文章

  1. Poj 3264 Balanced Lineup RMQ模板

    题目链接: Poj 3264 Balanced Lineup 题目描述: 给出一个n个数的序列,有q个查询,每次查询区间[l, r]内的最大值与最小值的绝对值. 解题思路: 很模板的RMQ模板题,在这 ...

  2. poj 3264 Balanced Lineup (RMQ)

    /******************************************************* 题目: Balanced Lineup(poj 3264) 链接: http://po ...

  3. poj 3264 Balanced Lineup【RMQ-ST查询区间最大最小值之差 +模板应用】

    题目地址:http://poj.org/problem?id=3264 Sample Input 6 3 1 7 3 4 2 5 1 5 4 6 2 2 Sample Output 6 3 0分析:标 ...

  4. POJ 3264 Balanced Lineup 【线段树/区间最值差】

    Balanced Lineup Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 62103 Accepted: 29005 Cas ...

  5. POJ 3264 Balanced Lineup RMQ ST算法

    题意:有n头牛,编号从1到n,每头牛的身高已知.现有q次询问,每次询问给出a,b两个数.要求给出编号在a与b之间牛身高的最大值与最小值之差. 思路:标准的RMQ问题. RMQ问题是求给定区间内的最值问 ...

  6. poj 3264 Balanced Lineup (RMQ算法 模板题)

    RMQ支持操作: Query(L, R):  计算Min{a[L],a[L+1], a[R]}. 预处理时间是O(nlogn), 查询只需 O(1). RMQ问题 用于求给定区间内的最大值/最小值问题 ...

  7. POJ 3264 Balanced Lineup -- RMQ或线段树

    一段区间的最值问题,用线段树或RMQ皆可.两种代码都贴上:又是空间换时间.. RMQ 解法:(8168KB 1625ms) #include <iostream> #include < ...

  8. POJ 3264 Balanced Lineup 【ST表 静态RMQ】

    传送门:http://poj.org/problem?id=3264 Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total S ...

  9. POJ 3264 Balanced Lineup【线段树区间查询求最大值和最小值】

    Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 53703   Accepted: 25237 ...

随机推荐

  1. 实用Linux命令

    lsof -i:6379 查看某个端口的程序有没有起起来. netstat -tnlp 可以查看监听的端口,其中l是listening, p是显示program, n是显示ip而不是name, t看起 ...

  2. Cocos2d-x 2.x 升级为 3.x 常见变化纪录

    1.去CC 之前2.0的CC**,把CC都去掉,主要的元素都是保留的 2.0 CCSprite  CCCallFunc CCNode .. 3.0 Sprite CallFunc Node .. 2. ...

  3. Java中字符串相等与大小比較

    在C++中,两个字符串比較的代码能够为: (string1==string2) 但在java中,这个代码即使在两个字符串全然同样的情况下也会返回false Java中必须使用string1.equal ...

  4. RaceWeb介绍(7):由500强公司数据高速生成百度地图——生成坐标字段及坐标数据

    接上篇. 一.生成X坐标.Y坐标两个字段. 我们须要为每一个公司建立X坐标和Y坐标字段,用来保存XY坐标. 既然为了突出"快",这一步就有程序来完毕吧. 右键单击"世界5 ...

  5. 同步网络时间到linux服务器(先修改时区再进行同步网络时间)

    查看时区:date -R 修改整个系统时区: rm -f /etc/localtime ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 网 ...

  6. ant design pro (八)构建和发布

    一.概述 原文地址:https://pro.ant.design/docs/deploy-cn 二.详细 2.1.构建 当项目开发完毕,只需要运行一行命令就可以打包你的应用: npm run buil ...

  7. javascript 作用域 通俗解释

    首先将作用域比喻为一座大楼: 第一层表示当前执行作用域.大楼顶层表示全局作用域. (1)js首先会在当前楼层进行查找变量,如果没有找到,就做电梯往上一层(二层)楼查找. (2)若还是没有找到继续往上查 ...

  8. 如何知道TSQL语句已经运行了多久

    如何知道TSQL语句已经运行了多久 ,) --millisecond per tick --如果datediff 函数导致溢出 把下面的millisecond改为second 毫秒改为秒 SELECT ...

  9. spring各种邮件发送

    参考地址一 参考地址二 参考地址三 参考地址四 Spring邮件抽象层的主要包为org.springframework.mail.它包括了发送电子邮件的主要接口MailSender,和值对象Simpl ...

  10. 阿里云rds linux平台使用wget 工具下载备份与日志文件

    1. 获取备份下载地址 RDS 控制台  备份恢复  数据备份,选择需要下载的备份集,点击“下载”. 点击“复制内网地址” 或 “复制外网地址” 来获取备份的 内网 或 外网 下载地址. 日志备份的地 ...