1. 程式人生 > >【學習筆記】ST表

【學習筆記】ST表

ngs mes eve each test mil using des 最小值

【學習筆記】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.

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.

輸入:

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 ≤ A ≤ B ≤ N), representing the range of cows from A to B inclusive.

輸出:

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表