ST表(Sparse Table稀疏表)
主要用于解决RMQ(区间最值问题)
问题描述: 给定N个数字, M次查询, 每次查询给定去间[L, R], 求区间内的最大值.
N <= 1e5, M <= 1e5
暴力肯定是不行了, 大家估计都会线段树, 线段树可以区间查询, 也可以区间更新, 功能很多, 但是建树O(N), 查询是O(logN).
随着M增大, O(logN)的查询不够优秀了, 我们需要O(1)查询!!!
于是乎, 我们不需要区间更新等操作而只需要区间查询的时候, 我们选择ST表.
ST表的核心是:
f(i,j)=max(f(i,j−1),f(i+2^(j−1),j−1);
f(i, j)代表的是从i开始(包括i)的共2^j个数字长度的区间的最大/小值.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #include <bits/stdc++.h> using namespace std; const int maxN = 1e5;
int a[maxN + 10]; int lg[maxN + 10]; int maxn[maxN + 10][50];
int main() { int n, m; cin >> n >> m; for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); lg[i] = lg[i / 2] + 1; } for (int i = 1; i <= n; i++) { maxn[i][0] = a[i]; } for (int i = 1; i <= lg[n]; i++) { for (int j = 1; j + (1 << i) - 1 <= n; j++) { maxn[j][i] = max(maxn[j][i - 1], maxn[j + (1 << n)][i - 1]); } } int l, r; while (m--) { scanf("%d %d", &l, &r); int len = lg[r - l + 1]; printf("%d\n", max(maxn[l][len], maxn[r - (1 << len) + 1][len])); } return 0; }
|
啊这,
Author:
Qin Peng
License:
Copyright (c) 2020 BY QPWLKQ LICENSE
Slogan:
每一个不曾起舞的日子, 都是对生命的辜负