#所需头文件:

#include <iostream>
#include <vector>
#include <initializer_list>
#include <algorithm>
#include <cmath>

代码(粘贴至程序定义头文件后)

template<typename type>
class _rmq {
private:
    std::vector<type> arr;
    std::vector<std::vector<type>> st;
    std::vector<int> log_table;
    int n = 0;
    bool inited = false;
    bool check_type() const {
        return std::is_same_v<type, short> ||
               std::is_same_v<type, unsigned short> ||
               std::is_same_v<type, int> ||
               std::is_same_v<type, unsigned int> ||
               std::is_same_v<type, long> ||
               std::is_same_v<type, unsigned long> ||
               std::is_same_v<type, long long> ||
               std::is_same_v<type, unsigned long long> ||
               std::is_same_v<type, float> ||
               std::is_same_v<type, double> ||
               std::is_same_v<type, long double>;
    }
    type gcd(type a, type b) const {
        a = a < 0 ? -a : a;
        b = b < 0 ? -b : b;
        while (b != 0) {
            type t = b;
            b = a % b;
            a = t;
        }
        return a;
    }
    void pre_log() {
        log_table.resize(n + 1);
        log_table[1] = 0;
        for (int i = 2; i <= n; ++i)
            log_table[i] = log_table[i / 2] + 1;
    }

    void build_max() {
        int k = log_table[n] + 1;
        st.assign(k, std::vector<type>(n));
        st[0] = arr;
        for (int j = 1; j < k; ++j)
            for (int i = 0; i + (1 << j) <= n; ++i)
                st[j][i] = std::max(st[j-1][i], st[j-1][i + (1 << (j-1))]);
    }

    void build_min() {
        int k = log_table[n] + 1;
        st.assign(k, std::vector<type>(n));
        st[0] = arr;
        for (int j = 1; j < k; ++j)
            for (int i = 0; i + (1 << j) <= n; ++i)
                st[j][i] = std::min(st[j-1][i], st[j-1][i + (1 << (j-1))]);
    }

    void build_or() {
        int k = log_table[n] + 1;
        st.assign(k, std::vector<type>(n));
        st[0] = arr;
        for (int j = 1; j < k; ++j)
            for (int i = 0; i + (1 << j) <= n; ++i)
                st[j][i] = st[j-1][i] | st[j-1][i + (1 << (j-1))];
    }

    void build_and() {
        int k = log_table[n] + 1;
        st.assign(k, std::vector<type>(n));
        st[0] = arr;
        for (int j = 1; j < k; ++j)
            for (int i = 0; i + (1 << j) <= n; ++i)
                st[j][i] = st[j-1][i] & st[j-1][i + (1 << (j-1))];
    }

    void build_xor() {
        int k = log_table[n] + 1;
        st.assign(k, std::vector<type>(n));
        st[0] = arr;
        for (int j = 1; j < k; ++j)
            for (int i = 0; i + (1 << j) <= n; ++i)
                st[j][i] = st[j-1][i] ^ st[j-1][i + (1 << (j-1))];
    }

    void build_gcd() {
        int k = log_table[n] + 1;
        st.assign(k, std::vector<type>(n));
        st[0] = arr;
        for (int j = 1; j < k; ++j)
            for (int i = 0; i + (1 << j) <= n; ++i)
                st[j][i] = gcd(st[j-1][i], st[j-1][i + (1 << (j-1))]);
    }

    void check() const {
        if (!check_type() || !inited) std::abort();
    }
    void idx(int i) const { if (i < 0 || i >= n) std::abort(); }
    void range(int l, int r) const { if (l < 0 || r >= n || l > r) std::abort(); }

public:
    _rmq() {}

    void give_size(int len) {
        if (len <= 0 || !check_type()) std::abort();
        n = len; arr.clear(); inited = false;
    }

    void give_content(std::initializer_list<type> ls) {
        if ((int)ls.size() != n || !check_type()) std::abort();
        arr.assign(ls.begin(), ls.end());
        pre_log(); inited = true;
    }

    type query(int i) {
        check(); idx(i); return arr[i];
    }

    type query_max(int l, int r) {
        check(); range(l, r); build_max();
        int len = r-l+1, k = log_table[len];
        return std::max(st[k][l], st[k][r-(1<<k)+1]);
    }
    type query_max() { return query_max(0, n-1); }

    type query_min(int l, int r) {
        check(); range(l, r); build_min();
        int len = r-l+1, k = log_table[len];
        return std::min(st[k][l], st[k][r-(1<<k)+1]);
    }
    type query_min() { return query_min(0, n-1); }

    type query_or(int l, int r) {
        check(); range(l, r); build_or();
        int len = r-l+1, k = log_table[len];
        return st[k][l] | st[k][r-(1<<k)+1];
    }
    type query_or() { return query_or(0, n-1); }

    type query_and(int l, int r) {
        check(); range(l, r); build_and();
        int len = r-l+1, k = log_table[len];
        return st[k][l] & st[k][r-(1<<k)+1];
    }
    type query_and() { return query_and(0, n-1); }

    type query_xor(int l, int r) {
        check(); range(l, r); build_xor();
        int len = r-l+1, k = log_table[len];
        return st[k][l] ^ st[k][r-(1<<k)+1];
    }
    type query_xor() { return query_xor(0, n-1); }

    type query_gcd(int l, int r) {
        check(); range(l, r); build_gcd();
        int len = r-l+1, k = log_table[len];
        return gcd(st[k][l], st[k][r-(1<<k)+1]);
    }
    type query_gcd() { return query_gcd(0, n-1); }
};

#功能: 定义 _rmq q;

其中type仅支持short,unsigned short,int,unsigned int,long int,unsigned long int,long long,unsigned long long,float,double,long double。

还可以定义_rmq q[a],_rmq q[a][b]等多重嵌套,表示一个多维数组,每个元素都是一个_rmq结构

赋值 q.give_size(n):将q的长度定义为n

q.give_content( {x0,x1……x[n-1]}):定义本数据结构内容,下标为0~n-1

必须按顺序执行定义、设置长度、赋值才可执行其他操作,对于数组内套_rmq,单个元素定义完成后即可访问该元素,但仍然不可访问其他未定义、设置长度、赋值元素。若出现此错误行为,会RTE

区间查询 q.query(l):返回一个数,表示q[i]的值

q.query_max(l,r):查询[l,r]区间最大值,若无元素q.query_max()则为查询整个数组的区间最大值

把max替换:min(最小),or(按位或),and(按位与),xor(安慰异或),gcd(最大公约数)。

#基于ST表实现

来自 https://www.oi-coding.cn/

0 条评论

目前还没有评论...