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; } };
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】