poj 3264 区间最大最小值 RMQ问题之Sparse_Table算法

Balanced Lineup

Time Limit: 5000 MS Memory Limit: 0 KB

64-bit integer IO format: %I64d , %I64u Java class name: Main

[Submit] [Status] [Discuss]

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..N+Q+1: Two integers A and B (1 ≤ ABN), 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
///RMQ问题之Sparse_Table算法  模板 区间最大最小值

#include <math.h>
#include <stdio.h>
#include <iostream>

#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b

using namespace std;
const int N=100005;
int n,Q,c[N],a,b;
int dp_max[N][33];  ///33足够用 2^32 是 int
int dp_min[N][33];

void Init()
{
    for(int i=1; i<=n; i++)
        dp_max[i][0] = dp_min[i][0] = c[i];
    double limit = log(n)/log(2.0);
    for(int j=1; j<=(int)limit; j++)
        for(int i=1; i+(1<<j)-1<=n; i++)
        {
            dp_max[i][j] = max(dp_max[i][j-1],dp_max[i+(1<<(j-1))][j-1]);
            dp_min[i][j] = min(dp_min[i][j-1],dp_min[i+(1<<(j-1))][j-1]);
        }
}
int Get_Max(int a,int b)
{
    int k = (int)(log(b-a+1)/log(2.0));
    return max(dp_max[a][k],dp_max[b-(1<<k)+1][k]);
}
int Get_Min(int a,int b)
{
    int k = (int)(log(b-a+1)/log(2.0));
    return min(dp_min[a][k],dp_min[b-(1<<k)+1][k]);
}
int main()
{
    scanf("%d%d",&n,&Q);
    for(int i=1; i<=n; i++)
        scanf("%d",&c[i]);
    Init();
    while(Q--)
    {
        scanf("%d%d",&a,&b);
        printf("%d\n",Get_Max(a,b)-Get_Min(a,b));
    }
    return 0;
}

RMQ问题,全名(Range Minimum/Maximum Query),是求给定区间中的最值问题。

主要方法及复杂度如下:

1、朴素(即搜索),O(n)-O(qn) online。

2、线段树,O(n)-O(qlogn) online。

3、Sparse_Table(实质是动态规划),O(nlogn)-O(1) online。

4、RMQ标准算法:先规约成LCA(Lowest Common Ancestor),再规约成约束RMQ,O(n)-O(1) online。

ST算法可以在O(nlogn)的预处理以后实现O(1)的查询效率,从而解决查询次数很多(如大于100万)的RMQ问题。

首先,是预处理。预处理是采用dp的思想,我们用f[i][j]表示区间[i,i+2^j-1]中的最大值(即从i开始,长度为2^j的闭区间)。

开始时,f[i][0]一定等于num[i]。好了,初始值找到了,下面是状态转移方程:

f[i][j]=max(f[i][j-1],f[i+2^(j-1)][j-1])。即把[i,i+2^j-1]区间分成两部分[i,i+2^(j-1)-1]和[i+2^(j-1),i+2^(j-1)+2^(j-1)-1],正好和原区间一致。

有了初始值和转移方程,我们可以自底向上递推出所有的f[i][j]的值。

对于边界,还要注意一点。由于区间长度最大为n,所以二维边界最大为log(n)/log(2.0);

一维边界只要满足对于每个起始点,都可以有长度找到n就行了,也就是让i+2^j-1<=n就好了。

然后就是查询了。假设要查询区间[a,b]的最大值,由于区间的长度很可能不是2的整数幂,所以我们要把区间划分为长度为2的整数幂的两部分,而且
这两个区间的并集必须是[a,b]。为了实现这个方案,我们需要先求出一个最大的k,使得2^k<=(b-a+1),这样就可以把区间分成两部分
[a,a+2^k-1]和[b-2^k+1,b],使他们既能不超过a,b区间的范围,又能把区间全部覆盖。于是,[a,b]区间的最大值就等于上述两个
区间的最大值中最大的那个。(有点绕)

poj 3264 区间最大最小值 RMQ问题之Sparse_Table算法

时间: 2024-12-22 13:06:36

poj 3264 区间最大最小值 RMQ问题之Sparse_Table算法的相关文章

POJ 3264 区间最大最小值Sparse_Table算法

题目链接:http://poj.org/problem?id=3264 Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 47515   Accepted: 22314 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up i

RMQ 问题之Sparse_Table算法

RMQ问题,全名(Range Minimum/Maximum Query),是求给定区间中的最值问题. 主要方法及复杂度如下: 1.朴素(即搜索),O(n)-O(qn) online. 2.线段树,O(n)-O(qlogn) online. 3.Sparse_Table(实质是动态规划),O(nlogn)-O(1) online. 4.RMQ标准算法:先规约成LCA(Lowest Common Ancestor),再规约成约束RMQ,O(n)-O(1) online. 昨天刚刚学了第三种,ST算

【RMQ】【Sparse_Table算法】

定义: RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题: 对于长度为n的数列A,回答若干询问RMQ(A,i,j) (i,j<=n),返回数列A中下标在i,j之间的最小/大值. 此类问题的解决方法有很多,暴力(当然也就说说,基本没有出题的会让你暴过去).线段树(复杂度为O(nlogn)).以及一个非常有名的在线处理RMQ问题的算法 -- Sparse_Table算法,简称ST算法,该算法能在进行O(nlogn)的预处理后达到查询O(1)的效率.主

POJ 3264:Balanced Lineup Rmq模板

Balanced Lineup 题目链接: http://poj.org/problem?id=3264 题意: 求区间最大值和最小值的差 题解: Rmq模板题 代码 #include<stdio.h> #include<math.h> const int N=5e4+1; int dpmax[N][17]; int dpmin[N][17]; int mmax(int x,int y) { return x>y?x:y; } int mmin(int x,int y) {

poj 3264 Balanced Lineup(一维RMQ)

题意:每次操作求区间[L,R]中最大值与最小值之差: 参考:http://blog.csdn.net/liang5630/article/details/7917702 思路:可以用线段树写,但ST算法求RMQ更方便: dp[i][j]表示从第i个数开始到i+2^j中的最值: 在操作之前,预处理出每段区间的最值,采用二分区间求极值的思想,降低复杂度: 查询时,覆盖查询区间,长度R-L+1,对于dp中,j=log(R-L+1),在这段区间中二分区间求极值即可; #include<cstdio>

(简单) POJ 3264 Balanced Lineup,RMQ。

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 rang

POJ 3264 Balanced Lineup(RMQ)

Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 36513   Accepted: 17103 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer Joh

poj 3264 Balanced Lineup(线段数求区间最大最小值)

链接:http://poj.org/problem?id=3264 Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 32772   Accepted: 15421 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order.

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分析:标准的模板题,可以用线段树写,但用RMQ-ST来写代码比较短.每次输出区间[L, R]内最大值和最小值的差是多少.注意一个地方,代码里面用到了log2()函数,但是我用包含<math.h>和<cmath>头文件的代码以C++的方式提交到POJ反馈是编译错误.改成g++提交才AC了.(注意