1. 程式人生 > >Luogu P2880 [USACO07JAN]平衡的陣容Balanced Lineup (ST表模板)

Luogu P2880 [USACO07JAN]平衡的陣容Balanced Lineup (ST表模板)

傳送門(ST表裸題)

ST表是一種很優雅的演算法,用於求靜態RMQ

陣列l[i][j]表示從i開始,長度為2^j的序列中的最大值

注意事項:

1.核心部分:

    for(int j = 1; (1<<j) <= n; j++)
        for(int i = 1; i+(1<<j)-1 <= n; i++) {
            l[i][j] = max(l[i][j-1],l[i+(1<<(j-1))][j-1]);
            s[i][j] = min(s[i][j-1],s[i+(1<<(j-1
))][j-1]); }

因為i~j的位數是j-i+1位,所以迴圈的邊界需要-1,而所求的兩段區間是不相交的,所以迴圈內不用-1(或者說,-1又+1了)

2.位運算需要頻繁地打括號

 

程式碼如下

#include<cstdio>
#include<iostream>
using namespace std;

const int maxn = 50005;
int n,q;
int a[maxn],l[maxn][50],s[maxn][50];
int al,as,x,y;

int main() {
    scanf("%d%d
",&n,&q); for(int i = 1; i <= n; i++){ scanf("%d",&a[i]); l[i][0] = a[i]; s[i][0] = a[i]; } for(int j = 1; (1<<j) <= n; j++) for(int i = 1; i+(1<<j)-1 <= n; i++) { l[i][j] = max(l[i][j-1],l[i+(1<<(j-1))][j-1
]); s[i][j] = min(s[i][j-1],s[i+(1<<(j-1))][j-1]); } while(q) { q--; scanf("%d%d",&x,&y); int k = 0; while(x+(1<<(k+1))<= y)k++; al = max(l[x][k],l[y-(1<<k)+1][k]); as = min(s[x][k],s[y-(1<<k)+1][k]); printf("%d\n",al-as); } return 0; }