题解:BISHI125 【模板】静态区间最值

题目链接

静态区间最值

题目描述

给定长度为 的数组 ,共 次操作:

  • 操作 1 l r:询问区间最小值
  • 操作 2 l r:询问区间最大值

解题思路

静态区间最值典型做法:ST 表(Sparse Table)。

  • 预处理 表与 表示区间 的最小/最大值;
  • 单次查询 ,令
    • 最小值为
    • 最大值为 。 时间复杂度:预处理 ,查询 ;空间

代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m; if (!(cin >> n >> m)) return 0;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; ++i) cin >> a[i];
    int LOG = 1; while ((1 << LOG) <= n) ++LOG;
    vector<int> lg(n + 1, 0); for (int i = 2; i <= n; ++i) lg[i] = lg[i >> 1] + 1;
    vector<vector<int>> stMin(LOG, vector<int>(n + 1));
    vector<vector<int>> stMax(LOG, vector<int>(n + 1));
    for (int i = 1; i <= n; ++i) stMin[0][i] = stMax[0][i] = a[i];
    for (int k = 1; k < LOG; ++k) {
        int len = 1 << k, half = len >> 1;
        for (int i = 1; i + len - 1 <= n; ++i) {
            stMin[k][i] = min(stMin[k-1][i], stMin[k-1][i + half]);
            stMax[k][i] = max(stMax[k-1][i], stMax[k-1][i + half]);
        }
    }
    auto qMin = [&](int l, int r) {
        if (l > r) swap(l, r);
        int k = lg[r - l + 1];
        return min(stMin[k][l], stMin[k][r - (1 << k) + 1]);
    };
    auto qMax = [&](int l, int r) {
        if (l > r) swap(l, r);
        int k = lg[r - l + 1];
        return max(stMax[k][l], stMax[k][r - (1 << k) + 1]);
    };

    while (m--) {
        int op, l, r; cin >> op >> l >> r;
        if (op == 1) cout << qMin(l, r) << '\n';
        else cout << qMax(l, r) << '\n';
    }
    return 0;
}
import java.io.*;

public class Main {
    static class FastScanner {
        private final InputStream in; private final byte[] buf = new byte[1<<16];
        private int p=0, l=0; FastScanner(InputStream is){in=is;}
        private int read() throws IOException { if(p>=l){ l=in.read(buf); p=0; if(l<=0) return -1; } return buf[p++]; }
        int nextInt() throws IOException { int c; int s=1,x=0; do{c=read();}while(c<=32); if(c=='-'){s=-1;c=read();} while(c>32){ x=x*10+(c-'0'); c=read(); } return x*s; }
    }

    public static void main(String[] args) throws Exception {
        FastScanner fs = new FastScanner(System.in);
        int n = fs.nextInt();
        int m = fs.nextInt();
        int[] a = new int[n+1];
        for (int i = 1; i <= n; i++) a[i] = fs.nextInt();
        int LOG = 1; while ((1 << LOG) <= n) ++LOG;
        int[] lg = new int[n+1]; for (int i = 2; i <= n; i++) lg[i] = lg[i>>1] + 1;
        int[][] stMin = new int[LOG][n+1];
        int[][] stMax = new int[LOG][n+1];
        for (int i = 1; i <= n; i++) stMin[0][i] = stMax[0][i] = a[i];
        for (int k = 1; k < LOG; k++) {
            int half = 1 << (k-1);
            for (int i = 1; i + (1<<k) - 1 <= n; i++) {
                stMin[k][i] = Math.min(stMin[k-1][i], stMin[k-1][i + half]);
                stMax[k][i] = Math.max(stMax[k-1][i], stMax[k-1][i + half]);
            }
        }
        StringBuilder out = new StringBuilder();
        while (m-- > 0) {
            int op = fs.nextInt();
            int l = fs.nextInt();
            int r = fs.nextInt();
            if (l > r) { int t=l; l=r; r=t; }
            int k = lg[r - l + 1];
            if (op == 1) {
                int ans = Math.min(stMin[k][l], stMin[k][r - (1<<k) + 1]);
                out.append(ans).append('\n');
            } else {
                int ans = Math.max(stMax[k][l], stMax[k][r - (1<<k) + 1]);
                out.append(ans).append('\n');
            }
        }
        System.out.print(out.toString());
    }
}
import sys

data = sys.stdin.buffer.read().split()
it = iter(data)
n = int(next(it)); m = int(next(it))
a = [0] * (n + 1)
for i in range(1, n + 1):
    a[i] = int(next(it))

LOG = 1
while (1 << LOG) <= n:
    LOG += 1
lg = [0] * (n + 1)
for i in range(2, n + 1):
    lg[i] = lg[i >> 1] + 1

stMin = [[0] * (n + 1) for _ in range(LOG)]
stMax = [[0] * (n + 1) for _ in range(LOG)]
for i in range(1, n + 1):
    stMin[0][i] = a[i]
    stMax[0][i] = a[i]
for k in range(1, LOG):
    seg_len = 1 << k
    half = seg_len >> 1
    # i in [1, n-seg_len+1]
    for i in range(1, n - seg_len + 2):
        stMin[k][i] = min(stMin[k-1][i], stMin[k-1][i + half])
        stMax[k][i] = max(stMax[k-1][i], stMax[k-1][i + half])

out_lines = []
for _ in range(m):
    op = int(next(it)); l = int(next(it)); r = int(next(it))
    if l > r:
        l, r = r, l
    k = lg[r - l + 1]
    if op == 1:
        ans = min(stMin[k][l], stMin[k][r - (1 << k) + 1])
    else:
        ans = max(stMax[k][l], stMax[k][r - (1 << k) + 1])
    out_lines.append(str(ans))
sys.stdout.write('\n'.join(out_lines))

算法及复杂度

  • 算法:ST 表(Sparse Table)
  • 时间复杂度:预处理 ,单次查询
  • 空间复杂度: