1. 程式人生 > >RMQ (Range Minimum/Maximum Query)問題的ST(Sparse Table)解法

RMQ (Range Minimum/Maximum Query)問題的ST(Sparse Table)解法

RMQ (Range Minimum/Maximum Query)問題,就是要求:數字序列區間最值。

如果直接遍歷查詢,複雜度為O(n).

對於比較大的資料和需要多次查詢的場景,都是很不理想的。

常見的方法有線段樹和Sparse Tabel兩種方法。

複雜度:

兩種演算法都需要預處理,預處理的複雜度為:

線段樹(segment tree) O(n)

ST(實質是動態規劃) O(nlogn)

查詢的複雜度:

線段樹(segment tree) O(qlogn) 

ST(實質是動態規劃)O(1)

Sparse Table 

這裡主要使用ST。

ST實際實際是動態規劃的實現,最小值為例:

用一個二維陣列f(i,j)記錄區間[i,i+2^j-1]區間中的最小值。//這個演算法的精妙所在

其中f[i,0] = a[i]; 

2'(j-1)+2^(j-1)=2^j;

所以:f(i,j)=min{f(i,j-1),f(i+2^(j-1),j-1)};

在預測理的時候需要考慮j的最大值。假設資料總數為N,當我們查詢最長的區間[0,N-1]之間的最值時,即需2^j-1>N;並且在dp的時候i + (1<<j) - 1 < N是就要停止。

自底向上。

void build_st_min(int n,int *num,int *f[MAXN]){
	int i,j;
	for(i=0;i<n;i++)
		f[i][0]=num[i];
	int tmp=log((double)n)/log(2.0);
	for(j=1;j<=tmp;j++)//include value of tmp
		for(i=0;i+(1<<j)-1<n;i++)
			f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}


查詢:
假設要查詢從m到n這一段的最小值, 那麼我們先求出一個最大的k, 使得k滿足2^k <= (n - m + 1).(使用log函式,基變換)
於是我們就可以把[m, n]分成兩個長度為2^k的區間: [m, m+2^k-1], [n-2^k+1, n](這兩個區間部分重疊);
而我們之前已經求出了f(m, k)為[m, m+2^k-1]的最小值, f(n-2^k+1, k)為[n-2^k+1,n-2^k+1+2^k-1]=[n-2^k+1, n]的最小值。
我們只要返回min{f(m,k),f(n-2^k+1,k)} 就是我們想要的答案, 這個演算法的時間複雜度是O(1)的.

int query_min(int a,int b,int *f[MAXN]){
	int k=(int)(log(b-a+1.0)/log(2.0));
	return min(f[a][k],f[b-(1<<k)+1][k]);//regional overlap
}


題目描述:
給定一個數字序列,查詢任意給定區間內數字的最小值。
輸入:
輸入包含多組測試用例,每組測試用例的開頭為一個整數n(1<=n<=100000),代表數字序列的長度。
接下去一行給出n個數字,代表數字序列。數字在int範圍內。
下一行為一個整數t(1<=t<=10000),代表查詢的次數。
最後t行,每行給出一個查詢,由兩個整數表示l、r(1<=l<=r<=n)。
輸出:
對於每個查詢,輸出區間[l,r]內的最小值。
樣例輸入:
5
3 2 1 4 3
3
1 3
2 4
4 5
樣例輸出:
1
1
3

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
const int MAXN=40;
void build_st_min(int n,int *num,int *f[MAXN]){
	int i,j;
	for(i=0;i<n;i++)
		f[i][0]=num[i];
	int tmp=log((double)n)/log(2.0);
	for(j=1;j<=tmp;j++)//include value of tmp
		for(i=0;i+(1<<j)-1<n;i++)
			f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
int query_min(int a,int b,int *f[MAXN]){
	int k=(int)(log(b-a+1.0)/log(2.0));
	return min(f[a][k],f[b-(1<<k)+1][k]);//regional overlap
}
int main()  
    {  
        int n,i,q,a,b;  
        while(scanf("%d ",&n)!=EOF)  
        {  
			int *num=new int[n];
			int **f=new int* [n];
			for(i=0;i<n;i++)
				f[i]=new int [MAXN];
            for(i=0;i<n;i++)  
                scanf("%d",&num[i]);  
            build_st_min(n,num,f);  
            scanf("%d",&q);
            for(i=0;i<q;i++)  
            {  
                scanf("%d%d",&a,&b);  
                printf("%d\n",query_min(a-1,b-1,f));  //start from 0
            }  
        }  
        return 0;  
    }  


參考:

相關推薦

RMQ (Range Minimum/Maximum Query)問題的STSparse Table解法

RMQ (Range Minimum/Maximum Query)問題,就是要求:數字序列區間最值。 如果直接遍歷查詢,複雜度為O(n). 對於比較大的資料和需要多次查詢的場景,都是很不理想的。 常見的方法有線段樹和Sparse Tabel兩種方法。 複雜度: 兩種演算法都

RMQ (Range Minimum/Maximum Query)演算法

RMQ演算法是一種查詢一個區間最值的演算法,當然是有Q次詢問,如果只詢問一次,當然直接遍歷就好了, 如果是詢問很多次,這時就需要RMQ演算法了。 RMQ演算法 RMQ演算法用的是DP求解, 預處理是nlogn的,查詢是O(1)。 A[i]表示要查詢的數列,F[i,j]

STSparse Table演算法基本思路及實現

ST演算法是在倍增的思想上建立的 來看一下ST演算法是怎麼實現的(以最大值為例): 首先是預處理,用一個DP解決。設a[i]是要求區間最值的數列,f[i,j]表示從第i個數起連續2^j個數中的最大值。 例如數列3 2 4 5 6 8 1 2 9 7 f[1,0]

ST算法Sparse Table

st算法 nbsp memset can cpp 最大 給定 sparse 繼續 RMQ問題: 給定一個序列,每次詢問一個區間最小值 / 最大值。 沒有修改。 //拿區間最大值來舉例。 memset(ans, -INF, sizeof(ans));

RMQ(Range minimum query) based LCA solution

何為RMQ 在文章《Tarjan’s off-line lowest common ancestors algorithm》我們用圖形化的方式展示了Tarjan’s off-line LCA的求解過程,但是該文章有很多遺漏,例如下面的這些問題。在本篇文章中,我會

LeetCode演算法題-Range Sum Query ImmutableJava實現

這是悅樂書的第204次更新,第214篇原創 01 看題和準備 今天介紹的是LeetCode演算法題中Easy級別的第70題(順位題號是303)。給定整數陣列nums,找到索引i和j(i≤j)之間的元素之和,包括端點。例如: 給定nums = [-2,0,3,-5,2,-1]

稀疏傅裏葉變換sparse FFT

存在 gauss 完成 可選 bsp mar hle 9.png res 作者:桂。 時間:2018-01-06 14:00:25 鏈接:http://www.cnblogs.com/xingshansi/p/8214122.html 前言   對於數字

Codechef:Expected Maximum Matching/MATCHHall定理

傳送門 題解: 利用Hall定理來判斷每個左邊集合是否滿足有完美匹配。 這樣是 O (

Hibernate--詳解Query物件 分頁

package com.itheima.b_api; import java.util.Arrays; import java.util.List; import org.hibernate.Criteria; import org.hibernate.Query; import org.h

931. Minimum Falling Path Sumpython+cpp

題目: Given a square array of integers A, we want the minimum sum of a falling path through A. A falling path starts at any element in the f

654. Maximum Binary Treepython+cpp

題目: Given an integer array with no duplicates. A maximum tree building on this array is defined as follow:  The root is the maximum number

CodeForces - 280B Maximum Xor Secondary單調棧

Bike loves looking for the second maximum element in the sequence. The second maximum element in the sequence of distinct numbers x1, x2, ...

1007 Maximum Subsequence Sum 25 分

1007 Maximum Subsequence Sum (25 分) Given a sequence of K integers { N​1​​, N​2​​, ..., N​K​​ }. A continuou

LeetCode—209—Minimum Size Subarray Sum滑動視窗

題目 Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If the

CF 280B -——Maximum Xor Secondary單調棧

Bike loves looking for the second maximum element in the sequence. The second maximum element in the sequence of distinct numbers x1, x2, ..., xk

PAT--1007 Maximum Subsequence Sum 25 分

1007 Maximum Subsequence Sum (25 分) Given a sequence of K integers { N​1, N​2​​ , …, N,​K ​​ }. A continuous subsequence is defined to be { N​

01-複雜度2 Maximum Subsequence Sum25 分

Given a sequence of K integers { N​1​​, N​2​​, ..., N​K​​ }. A continuous subsequence is defined to be { N​i​​, N​i+1​​, ..., N​j​​ } wher

1007 Maximum Subsequence Sum25 分PAT甲級

Problem Description: Given a sequence of K integers { N​1​​, N​2​​, ..., N​K​​ }. A continuous subsequence is defined to be { N​i​​, N​i+

PTA 01-複雜度2 Maximum Subsequence Sum 25 分

01-複雜度2 Maximum Subsequence Sum (25 分) Given a sequence of K integers { N​1​​, N​2​​, …, N​K​​ }. A continuous subsequence is defin

PAT (Advanced Level) 1007 Maximum Subsequence Sum 25 分

1007 Maximum Subsequence Sum (25 分) Given a sequence of K integers { N​1​​, N​2​​, …, N​K​​ }. A continuous subsequence is defined to be { N​i