【學習筆記】ST表
【學習筆記】ST表
給狂妄自負以適當的絕望,這就是真理
- RMQ問題:
給定一個長度為N的區間,M個詢問,每次詢問Li到Ri這段區間元素的最大值/最小值。
如果暴力找最大值,復雜度是o(n)。但如果查詢多次,這個復雜度就很大了。
解決這個問題的方法是離線ST表和支持在線修改的線段樹。 ST表:一種利用dp求解區間最值的倍增算法。
定義:f[i][j]表示i到i+2^j-1這段區間的最大值。
預處理:f[i][0]=a[i]。即i到i區間的最大值就是a[i]。
狀態轉移:將f[i][j]平均分成兩段,一段為f[i][j-1],另一段為f[i+2^(j-1)][j-1]。
兩段的長度均為2^j-1。f[i][j]的最大值即這兩段的最大值中的最大值。
f[i][j]=max(f[i][j-1],f[i+2^(j-1)][j-1])
- 查詢:需要查詢的區間為[i,j],則需要找到兩個覆蓋這個閉區間的最小冪區間。
這兩個區間可以重復,因為兩個區間是否相交對區間最值沒有影響。(如下圖)
模板題:Balanced Lineup
題目描述:
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.
輸入:
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 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.
樣例
6 3
1
7
3
4
2
5
1 5
4 6
2 2
6
3
0
#include <algorithm>
#include <cstdio>
#define ll long long
using namespace std;
const int maxn=1e5;
int stmax[maxn][20],stmin[maxn][20];
int poww[25],logg[maxn];
int n,q;
void init()
{
poww[0]=1;
for(int i=1; i<=20; i++)//預處理次方
{
poww[i]=poww[i-1]<<1;
}
for(int i=2; i<=n; i++)
{
logg[i]=logg[i>>1]+1;
}
int temp=1;
for(int j=1; j<=logg[n]; j++)//temp=2^(j-1)
{
for(int i=1; i<=n-temp-temp+1; i++)
{
stmax[i][j]=max(stmax[i][j-1],stmax[i+temp][j-1]);
stmin[i][j]=min(stmin[i][j-1],stmin[i+temp][j-1]);
}
temp<<=1;
}
}
inline int query_min(int l,int r)
{
int len=r-l+1;
int k=logg[len];
return min(stmin[l][k],stmin[r-poww[k]+1][k]);
}
inline int query_max(int l,int r)
{
int len=r-l+1;
int k=logg[len];
return max(stmax[l][k],stmax[r-poww[k]+1][k]);
}
int main()
{
int a;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
scanf("%d",&a);
stmax[i][0]=stmin[i][0]=a;
}
init();
int l,r;
while(q--){
scanf("%d%d",&l,&r);
printf("%d\n",query_max(l,r)-query_min(l,r));
}
return 0;
}
【學習筆記】ST表