跳表模型

跳表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;
    }
};

 

posted @ 2023-11-19 13:13  深渊之巅  阅读(6)  评论(0编辑  收藏  举报