題解/算法 {2940. 找到 Alice 和 Bob 可以相遇的建筑}
@LINK: https://leetcode.cn/problems/find-building-where-alice-and-bob-can-meet/
;
對於一個查詢(a,b)
:
@IF(a==b
或H[ min(a,b)] < H[ max(a,b)]
): 此時答案就是max(a,b)
;
@ELSE: 你需要在H[ max(a,b), ....]
這個後綴裡 找第一個滿足> max( H[a], H[b])
的元素;
.
做離線化處理, 即對查詢 根據max(a,b)
從大到小排序, 這樣 我們全局維護H[ max(a,b),...]
這個元素;
.
問題轉換為 對於[a1, a2, a3, ...]
找從左到右 第一個>x
的元素;
.
看一個錯誤做法, ai
放到set
裡, 然後upper_bound(x)
; 這是錯誤的 比如[5, 3, 7]
如果找upper_bound(1)
則你會找到3
而答案是5;
.
正確做法: 對於[5(a), 5(b), 3, 7]
使用單調棧思想 變成[5(a), 7]
即嚴格遞增序列, 當你讓set
裡放到一個x
時 如果set.begin() <= x
則把set.erase( set.begin())
, 不用考慮index
因為當前x
元素的下標 一定< set裡所有元素的index
;
.
然後答案為: set
找>x
的第一個元素, 由於set
的元素是pair<int,int>
即(val, index)
, 如果你寫成upper_bound(x, -1)
這是錯誤的 因為可能找到是(x, ?)
即第二維度會起作用 顯然這個元素並不滿足條件 因為我們要的是(>x, ?)
, 正確答案是 upper_bound( {x, 1e9})
讓第二維度最大 那麼找到的答案 一定是(>x, ?)
;
vector<int> leftmostBuildingQueries(vector<int>& H, vector<vector<int>>& Q) {
int N = H.size();
using T_ = tuple<int,int,int>;
vector< T_> Que( Q.size());
FOR_( i, 0, Q.size()-1){ Que[i] = {Q[i][0], Q[i][1], i};}
sort( Que.begin(), Que.end(), []( auto _a, auto _b){
return max(get<0>(_a), get<1>(_a)) > max(get<0>(_b), get<1>(_b)); });
vector<int> ANS( Q.size());
set< pair<int,int> > S;
int nn = N;
for( auto que : Que){
int a = get<0>(que), b = get<1>(que);
auto & curANS = ANS[ get<2>(que)];
if( a > b){ swap(a,b);}
if( H[a]<H[b] || a==b){ // 特判
curANS = b;
continue;
}
while( nn > max(a,b)){
-- nn;
while( !S.empty() && S.begin()->first <= H[nn]){ S.erase( S.begin());} // 單調棧
S.insert( {H[nn], nn});
}
auto it = S.upper_bound( {max(H[a], H[b]), 1e9});
if( it == S.end()){ curANS = -1;}
else{ curANS = it->second;}
}
return ANS;
}