范围最小值问题(Range Minimum Query,RMQ)

问题描述

给定一个n个元素的序列{A1,A2,……,An},在要求的区间Query(L,R)内找到最小值:min{AL,AL+1,……,AR}。hiho16

算法描述

在这里介绍最常用的Tarjan的Sparse-Table算法,它的预处理时间复杂度为O(nlogn),而查询时间只需要O(1)。令calc(i,j)表示从i开始的,长度为2j 的一段子序列的最小值,则使用循环的方式计算:calc[i][j] = min(calc[i][j-1],calc[i+2j-1)][j-1]),代码如下:

void RMQ_init(void){
    int index = floor(log(n) / log(2));
    for (int j = 1; j <= index; j++) {
        for (int i = 1; i+(1<<j)-1<=n; i++){
            calc[i][j] = min(calc[i][j-1],calc[i+(1<<(j-1))][j-1]);
        }
    }
}

注:这里序列从索引1开始。

预处理完成后,如何使用该信息呢,对于一个查询[L,R],只要找到小于这个区间长度的最大的2的非负整数次幂的指数——j,那么这个区间中的最小值就是min{calc[L][j], calc[R-2j+1][j]},通过这两段区间可以覆盖整个[L,R]区间,同时即使两端区间有交集也不影响最小值的确定。

代码

#include<cstdio>
#include<algorithm>
#include<math.h>
#define SIZE 1000005
using namespace std;
int arr[SIZE];
int calc[SIZE][20];
int n, q;
void RMQ_init(void){
    int index = floor(log(n) / log(2));
    for (int j = 1; j <= index; j++) {
        for (int i = 1; i+(1<<j)-1<=n; i++){
            calc[i][j] = min(calc[i][j-1],calc[i+(1<<(j-1))][j-1]);
        }
    }
}
int main(void) {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++){
        scanf("%d", arr + i);
        calc[i][0] = arr[i];
    }
    RMQ_init();
    scanf("%d", &q);
    int l, r;
    for (int i = 0; i < q; i++){
        scanf("%d%d", &l, &r);
        int j = floor(log(r - l + 1) / log(2));
        int rr = r - (1<<j) + 1;
        printf("%d\n", min(calc[l][j], calc[rr][j]));
    }
    return 0;
}
时间: 2024-10-20 13:13:12

范围最小值问题(Range Minimum Query,RMQ)的相关文章

Geeks - Range Minimum Query RMQ范围最小值查询

使用线段树预处理,可以使得查询RMQ时间效率在O(lgn). 线段树是记录某范围内的最小值. 标准的线段树应用. Geeks上只有两道线段树的题目了,而且没有讲到pushUp和pushDown操作,只是线段树的入门了. 参考:http://www.geeksforgeeks.org/segment-tree-set-1-range-minimum-query/ 我修改了一下他的程序,使用pushUp操作,其实也是很简单的一个小函数.而且手动计算了下,觉得他的动态分配内存,计算需要的树的大小,这样

AOJ DSL_2_A Range Minimum Query (RMQ)

Range Minimum Query (RMQ) Write a program which manipulates a sequence A = {a0,a1,...,an−1} with the following operations: find(s,t): report the mimimum element in as,as+1,...,at. update(i,x): change ai to x. Note that the initial values of ai (i=0,1

Segment Tree Range Minimum Query.

int rangeMinQuery(int segTree[], int qlow, int qhigh, int low, int high, int pos) { if (qlow <= low && qhigh >= high) return segTree[pos]; if (qlow > high || qhigh < low) return maxVal; int mid = (low + high) / 2; return min(rangeMinQu

2-D range sum query implementation(2-D segment tree)

Google interview question:一个二维数组,有两个方法,一个是update(x,y),更新一个cell的值,一个是query(x1,y1,x2,y2),查询(x1,y1,x2,y2)矩形内所有元素的和. Senario 1. update调用次数远大于query. Senario 2. query调用次数远大于update. Senario 3. 两种方法调用一样多. 对于senario 1,只需要用一个二维数组储存数据,update相应的cell,时间复杂度O(1),qu

[LeetCode] Range Sum Query 2D - Immutable

Very similar to Range Sum Query - Immutable, but we now need to compute a 2d accunulated-sum. In fact, if you work in computer vision, you may know a name for such an array --- Integral Image. To solve this problem, Stefan has already posted a very e

LeetCode:Range Sum Query - Immutable - 数组指定区间内的元素和

1.题目名称 Range Sum Query(数组指定区间内的元素和) 2.题目地址 https://leetcode.com/problems/range-sum-query-immutable/ 3.题目内容 英文:Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. 中文:给定一个数组nums,求出索引i和j之间元素的和,i一定是小于或等于j

Range Sum Query 2D - Mutable &amp; Immutable

Range Sum Query 2D - Mutable Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2). The above rectangle (with the red border) is defined by (row1,

leetCode 303. Range Sum Query - Immutable | Dynamic Programming

303. Range Sum Query - Immutable Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. Example: Given nums = [-2, 0, 3, -5, 2, -1] sumRange(0, 2) -> 1 sumRange(2, 5) -> -1 sumRange(0, 5) -> -3 Note:

LeetCode Range Sum Query - Mutable

原题链接在这里:https://leetcode.com/problems/range-sum-query-mutable/ 题目: Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. The update(i, val) function modifies nums by updating the element at index i to v