数据结构
原理
ST 表用于区间查询,尤其是可重复贡献的问题。基于倍增思想,实现 预处理, 响应每个查询。
例如区间求最值,区间 GCD 等,令 表示区间 的最大值,显然 , 那么有:
因此对于每一个查询 ,我们都能将其二分为两个子问题:
与 ,其中 。求两部分的最大值即为 内最大值。
实现
在查询前,我们需要先进行预处理,以保证每一个区间都得到覆盖。
模板题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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| #include <bits/stdc++.h> #define mod (int)(1e9 + 7) #define int long long #define endl '\n' #define pb push_back #define PII pair<int, int> #define PLL pair<ll, ll> #define fst first #define snd second #define LOGN 21 typedef long long ll; typedef unsigned long long ull; typedef long double ld; const int MAX = 0x3f3f3f3f; const ll LLMAX = 9223372036854775807; const double PI = acos(-1); using namespace std; inline void rd(ll &x) { x = 0; short f = 1; char c = getchar(); while ((c < '0' || c > '9') && c != '-') c = getchar(); if (c == '-') f = -1, c = getchar(); while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); x *= f; } inline void pt(ll x) { if (x < 0) putchar('-'), x = -x; if (x > 9) pt(x / 10); putchar(x % 10 + '0'); } ll f[(int)1e5 + 10][LOGN + 1]; void solve() { int N, M; int l, r, s; rd(N); rd(M); for (int i = 1; i <= N; i++) rd(f[i][0]); for (int j = 1; j <= LOGN; j++) for (int i = 1; i + (1 << j) - 1 <= N; i++) f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); for (int i = 1; i <= M; i++) { rd(l); rd(r); s = floor(log2(r - l + 1)); pt(max(f[l][s], f[r - (1 << s) + 1][s])); putchar('\n'); } } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t = 1; while (t--) solve(); return 0; }
|