前言
思路
首先看数据范围 $10^5$,$O(n \log_2 n)$ 可以过,自然想到二分。
二分具有单调性,那么如何确保整个 $a$ 序列按顺序排列呢?
我们可以使用 st 表维护区间最大值,如果在这个距离中已经有了 $a_i\ge b_j$ 那么最大值一定指向的是新加入进来的那个值,否则在之前二分就已经不会再继续扩展了。
对于环形结构我们必须断环为链,这样可以将环形变为链形,并且保证答案的正确性。
这时我们就必须要考虑二分与断环为链了,因为二分会向右扩展 $mid$,所以两倍会越界,那么就需要开三倍。
那么我们如何判断无解呢?在 $l = n$ 时说明已经过了一圈但是还是没有找到 $a_i\ge b_j$,又回到了 $j$,说明无解。
#include <bits/stdc++.h>
using namespace std;
int n,a[300010],LOG2[300010],st[300010][30];
inline int read()
{
int x = 0,f = 1;char ch = getchar();
while (ch < '0' || ch > '9'){if(ch == '-') f = -1;ch = getchar();}
while (ch >= '0' && ch <= '9'){x = x * 10 + ch - 48;ch = getchar();}
return x * f;
}
void init(){
for(int i = 2;i <= 3 * n;i++)
LOG2[i] = LOG2[i >> 1] + 1;
for(int i = 1;i <= n;i++)
st[i][0] = st[i + n][0] = st[i + n + n][0] = a[i];
int k = LOG2[3 * n];
for(int i = 1;i <= k;i++)
for(int j = 1;j + (1 << i) - 1 <= 3 * n;j++){
st[j][i] = max(st[j][i - 1],st[j + (1 << i - 1)][i - 1]);
}
}
int num(int l,int r){
int s = LOG2[r - l + 1];
int x = max(st[l][s],st[r - (1 << s) + 1][s]);
return x;
}
int two(int x,int y){
int l = 1,r = n;
while(l < r){
int mid = (l + r) >> 1;
if(max(num(y - mid,y - 1),num(y + 1,y + mid)) >= x)
r = mid;
else
l = mid + 1;
}
return l == n ? -1 : l;
}
int main(){
n = read();
for(int i = 1;i <= n;++i)
a[i] = read();
init();
for(int i = 1;i <= n;i++){
int b = read();
printf("%d ",two(b,i + n));
}
return 0;
}
标签:二分,ch,JFCA,int,题解,mid,300010,P7333
From: https://www.cnblogs.com/JJL0610/p/17559920.html