chenfy27的刷题记录

导航

leetcode2940 找到Alice和Bob可以相遇的建筑

给出数组H[n]和多组询问Q[m],其中Q[i]={a[i],b[i]}表示查询最靠左的下标j,使得a[i]和b[i]都可以移到j处。从x处能移到y处的前提是x<y并且H[x]<H[y]。
1<=n<=5E4; 1<=H[i]<=1E9; 1<=m<=5E4; 0<=a[i],b[i]<=n-1

分析:相当于找最靠左的上限,可以用st表或线段树来维护区间最大值,然后二分找最左。另外注意a[i]=b[i]的情况,这点在二分check里不方便处理,因此在外层特判。

方法1、st表

const int N = 50004;
int n, a[N], Min[N][21], Max[N][21];
int qmin(int l, int r) {
    int k = log2(r + 1 - l);
    return min(Min[l][k], Min[r + 1 - (1 << k)][k]);
}
int qmax(int l, int r) {
    int k = log2(r + 1 - l);
    return max(Max[l][k], Max[r + 1 - (1 << k)][k]);
}
void build() {
    for (int i = 1; i <= n; i++) {
        Min[i][0] = Max[i][0] = a[i];
    }
    for (int j = 1; j <= 20; j++) {
        for (int i = 1; i + (1 << j) <= n + 1; i++) {
            Min[i][j] = min(Min[i][j - 1], Min[i + (1 << (j - 1))][j - 1]);
            Max[i][j] = max(Max[i][j - 1], Max[i + (1 << (j - 1))][j - 1]);
        }
    }
}

class Solution {
public:
    vector<int> leftmostBuildingQueries(vector<int>& H, vector<vector<int>>& Q) {
        n = H.size();
        for (int i = 1; i <= n; i++) {
            a[i] = H[i - 1];
        }
        build();
        int m = Q.size();
        vector<int> ans(m);
        for (int i = 0; i < m; i++) {
            int A = Q[i][0] + 1;
            int B = Q[i][1] + 1;
            if (A > B) std::swap(A,B);
            if (A == B || a[A] < a[B]) {
                ans[i] = B;
                continue;
            }
            int lo = B, hi = n, mid;
            while (lo < hi) {
                mid = lo + (hi - lo) / 2;
                int q = qmax(lo, mid);
                if (q > a[A] && q >= a[B])
                    hi = mid;
                else
                    lo = mid + 1;
            }
            if (B <= lo && lo <= n && qmax(lo, lo) > a[A] && qmax(lo, lo) >= a[B])
                ans[i] = lo;
            else
                ans[i] = 0;
        }
        for (auto &i : ans) i--;
        return ans;
    }
};

方法2、线段树

// 线段树模板...
struct Info {
    int max = 0;
    Info(int v=0):max(v) {}
    friend Info operator+(const Info &a, const Info &b) {
        Info ans;
        ans.max = std::max(a.max, b.max);
        return ans;
    }
};

class Solution {
public:
    vector<int> leftmostBuildingQueries(vector<int>& heights, vector<vector<int>>& queries) {
        int n = heights.size();
        int q = queries.size();
        vector<int> ans(q);
        SegmentTree<Info> seg(heights);
        for (int i = 0; i < q; i++) {
            int x = queries[i][0];
            int y = queries[i][1];
            if (x > y) {
                std::swap(x, y);
            }
            if (x == y || heights[x] < heights[y]) {
                ans[i] = y;
                continue;
            }
            ans[i] = seg.findFirst(y + 1, n, [&](const Info &info){
                return info.max > heights[x] && info.max > heights[y];
            });
        }
        return ans;
    }
};

posted on 2024-03-24 10:40  chenfy27  阅读(26)  评论(0)    收藏  举报