- 分享
_rmq类
- @ 2026-5-17 12:14:33
#所需头文件:
#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 条评论
目前还没有评论...
京公网安备 11011102002149号