给出数组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表或线段树来维护区间最大值,然后二分找最左。由于是静态数据,这里选择st表来维护。另外要注意a[i]=b[i]的情况,这点在二分check里不好处理,因此在外层特判。
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=b;i>=a;i--)
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() {
rep(i,1,n) Min[i][0] = Max[i][0] = a[i];
rep(j,1,20) {
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();
rep(i,1,n) 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) 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;
}
};
标签:lc2940,Min,int,lo,Alice,mid,hi,ans,Bob
From: https://www.cnblogs.com/chenfy27/p/18092150