962. 最大宽度坡(权值线段树, 权值树状数组)

发布时间 2023-10-19 17:51:16作者: 深渊之巅

 本题要快速找到某个数字在数组中左边<=它的数的最小下标。

可以建立一个权值线段树,nums[i]处维护最小下标。

class Solution {
public:

    const static int N = 50010, INF = 0x3f3f3f3f;

    struct Node {
        int l, r, v;
    } tr[N * 4];

    void pushup(int u) {
        tr[u].v = min(tr[u << 1].v, tr[u << 1 | 1].v);
    }

    void build(int u, int l, int r) {
        tr[u] = {l, r, INF};
        if(l == r) return;
        int mid = l + r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }

    void update(int u, int x, int v) {
        if(tr[u].l == tr[u].r) {
            tr[u].v = min(tr[u].v, v);
            return;
        }
        int mid = tr[u].l + tr[u].r >> 1;
        if(x <= mid) update(u << 1, x, v);
        else update(u << 1 | 1, x, v);
        pushup(u);
    }

    int query(int u, int l, int r) {
        if(tr[u].l >= l && tr[u].r <= r) {
            return tr[u].v;
        }
        int res = INF;
        int mid = tr[u].l + tr[u].r >> 1;
        if(l <= mid) res = min(res, query(u << 1, l, r));
        if(r > mid) res = min(res, query(u << 1 | 1, l, r));
        return res;
    }

    int maxWidthRamp(vector<int>& nums) {
        int mx = *max_element(nums.begin(), nums.end()), n = nums.size();
        build(1, 0, mx);
        int ans = 0;

        for(int i = 0; i < n; i ++ ) {
            int p = query(1, 0, nums[i]);
            if(p < i) ans = max(ans, i - p);
            update(1, nums[i], i);
        }

        return ans;
    }
};

 

权值树状数组

class Solution:
    def maxWidthRamp(self, nums: List[int]) -> int:
        n, ans = len(nums), 0
        tree = [0x3f3f3f3f] * (int(5e4)+5)

        def update(u: int, v: int) -> None:
            while u < len(tree):
                tree[u] = min(tree[u], v)
                u += u & -u
        
        def query(u: int) -> int:
            res = tree[u]
            while u:
                res = min(res, tree[u])
                u -= u & -u
            return res

        for i, e in enumerate(nums):
            ans = max(ans, i - query(e + 1))
            update(e + 1, i)

        return ans