st表

st表

1簡潔

st表能夠\(nlogn\)預處理,O1查詢,相對於線段樹的logn查詢相對有優點,可是st表只能支持靜態解決RMQ,這是一個很是大的劣勢。html

2.講解

ST表是利用的是倍增的思想ios

拿最大值來講spa

咱們用𝑀𝑎𝑥[𝑖][𝑗]Max[i][j]表示,從𝑖i位置開始的2𝑗2j個數中的最大值,例如𝑀𝑎𝑥[𝑖][1]Max[i][1]表示的是𝑖i位置和𝑖+1i+1位置中兩個數的最大值code

那麼轉移的時候咱們能夠把當前區間拆成兩個區間並分別取最大值(注意這裏的編號是從11開始的)htm

img

查詢的時候也比較簡單blog

咱們計算出𝑙𝑜𝑔2(區間長度)log2(區間長度)get

而後對於左端點和右端點分別進行查詢,這樣能夠保證必定能夠覆蓋查詢的區間string

剛開始學的時候我不太理解爲何從右端點開始查的時候左端點是𝑟−2𝑘+1r−2k+1it

實際很簡單,由於咱們須要找到一個點𝑥x,使得𝑥+2𝑘−1=𝑟x+2k−1=rio

這樣的話就能夠獲得𝑥=𝑟−2𝑘+1

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<deque>
#include<cstdlib>
#include<ctime>
#define dd double
#define ll long long
#define ld long double
#define ull unsigned long long
#define N 100010
#define M number
using namespace std;

const int INF=0x3f3f3f3f;

int n,m,a[N];
int sum[N][50];

inline int Min(int a,int b){
	return a>b?b:a;
}

inline int Max(int a,int b){
	return a>b?a:b;
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
//	memset(sum,INF,sizeof(sum));
	for(int i=1;i<=n;i++) sum[i][0]=a[i];
	for(int i=1;(1<<i)<=n;i++)
		for(int j=1;j+(1<<i)-1<=n;j++)
			sum[j][i]=Max(sum[j][i-1],sum[j+(1<<(i-1))][i-1]);
	for(int i=1;i<=m;i++){
		int l,r;
		scanf("%d%d",&l,&r);
		int k=log2(r-l+1);
		int minn=Max(sum[l][k],sum[r-(1<<k)+1][k]);
		printf("%d\n",minn);
	}
}

引用註明

<http://www.javashuo.com/article/p-hgfqospn-ev.html

相關文章
相關標籤/搜索