跳表模型
跳表RMQ算法
求解静态区间最值的一种算法。
f[i][j] 表示 从i出发,长度为2^j这一段区间的最大值。
初始化和递推:
void init() { for(int j = 0; j < M; j ++ ) { for(int i = 1; i + (1 << j) - 1 <= n; i ++ ) { if(!j) f[i][j] = w[i]; else f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]); } } }
查询:
// 要查询[L, R]区间最值,我们取一个k,k满足2^k <= len。
// 我们要查询的值即为: max(f[l][k], f[r - (1 << k) + 1][k]) 以左端点为起点,长度为2^k的最值,和以r为终点,长度为2^k的最值,二者再取一个最值。
int query(int l, int r) {
int k = __lg(r - l + 1);
return max(f[l][k], f[r - (1 << k) + 1][k]); }
简单的求区间最值
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int N = 2e5 + 10, M = 18; int n, m; int f[N][M]; int w[N]; void init() { for(int j = 0; j < M; j ++ ) { for(int i = 1; i + (1 << j) - 1 <= n; i ++ ) { if(!j) f[i][0] = w[i]; else f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]); } } } int query(int l, int r) { int k = __lg(r - l + 1); return max(f[l][k], f[r - (1 << k) + 1][k]); } int main() { cin >> n; for(int i = 1; i <= n; i ++ ) cin >> w[i]; init(); cin >> m; while(m -- ) { int l, r; cin >> l >> r; cout << query(l, r) << endl; } return 0; }
解答本题的关键在于查出第i个位置右边第一个大于nums[i]的数字。
可以用跳表+二分,区间最值具有二分性, [l, r]的区间最值一定小于等于[l, r + c]的区间最值。
class Solution { public: const static int N = 50005, M = 17; int f[N][M]; void init(const vector<int> &a, int n) { for(int j = 0; j < M; j ++ ) { for(int i = 1; i <= n - (1 << j) + 1; i ++ ) { if(!j) f[i][j] = a[i - 1]; else { f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]); } } } } int query(int l, int r) { int k = __lg(r - l + 1); return max(f[l][k], f[r - (1 << k) + 1][k]); } vector<int> leftmostBuildingQueries(vector<int>& heights, vector<vector<int>>& queries) { int n = heights.size(), m = queries.size(); init(heights, n); vector<int> res(m); for(int i = 0; i < m; i ++ ) { int l = queries[i][0] + 1, r = queries[i][1] + 1; if(l > r) swap(l, r); if(l == r) res[i] = l - 1; else if(heights[l - 1] < heights[r - 1]) res[i] = r - 1; else { int L = r, R = n + 2; while(L + 1 < R) { int m = (L + R) >> 1; if(query(r + 1, m) > heights[l - 1]) R = m; else L = m; } if(L == n + 1) res[i] = -1; else res[i] = L; } } return res; } };