ST表
模板题:https://www.luogu.com.cn/problem/P3865
要注意的几个点就是ST表是用来求解可重复贡献问题的,也就是一个值可以被用来计算两次而不影响结果,也就是区间可以重叠。其他的看代码注释。。。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> //#define fre //#define DEBUG using namespace std; const int maxn = 100005, logm = 18; // logm后面在预处理的时候会用到 int f[maxn][logm], logto[maxn]; void pre() // 预处理log2的值 { logto[1] = 0, logto[2] = 1; for (int i = 3; i < maxn; ++i) { logto[i] = logto[i >> 1] + 1; // 用换底公式可以推出,但我一开始没想明白如果i是奇数会不会出错,因为此时log[i]=log[i-1] // 但实际上log[i-1]<=log[i],如果是错的话那么只能log[i-1]=log[i]-1,产生这种情况只可能 // 是i在2的n次方的分界点,又因i是奇数,假设i=2^n+1,log[i-1]=n=log[i]仍然成立。 } } int main() { #ifdef fre freopen("in.in", "r", stdin); freopen("out.txt", "w", stdout); #endif int n, m, l, r; pre(); scanf("%d%d", &n, &m); for (int i = 0; i < n; ++i) scanf("%d", &f[i][0]); // 注意这里的循环顺序 for (int j = 1; j < logm; ++j) { for (int i = 0; i + (1 << j) - 1 < n; ++i) // 注意这里的范围控制,保证当前更新的区间的右端点小于n { f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); } } for (int i = 0; i < m; ++i) { scanf("%d%d", &l, &r); --l, --r; int t = logto[r - l + 1]; printf("%d\n", max(f[l][t], f[r - (1 << t) + 1][t])); } }

浙公网安备 33010602011771号