二分查找
二分查找,即查询有序数组中某个数的前驱/后继,为了偷懒 ,我们一般用:
lower_bound(array.begin() , array.end() , number)-array.begin()
upper_bound(array.begin() , array.end() , number)-array.begin()
array可以换成set,可以氵掉一些平衡树的题。
例题1:
题目来源:
https://codeforces.com/contest/1721/problem/C
题意:
给定序列
{
a
n
}
\{a_n\}
{an},
{
b
n
}
\{b_n\}
{bn},构造序列
{
d
n
}
\{d_n\}
{dn},使得
b
i
=
a
i
+
d
i
b_i=a_i+d_i
bi=ai+di,求
m
a
x
{
d
i
}
max\{d_i\}
max{di},
m
i
n
{
d
i
}
min\{d_i\}
min{di}。
思路:
m
i
n
{
d
i
}
min\{d_i\}
min{di}好求,在
{
b
n
}
\{b_n\}
{bn}中查询
a
i
a_i
ai的后继,作差即可。可以用双指针,也可以用二分查找,用二分查找更好写。
对于
m
a
x
{
d
i
}
max\{d_i\}
max{di},我们取
b
j
−
a
i
b_j-a_i
bj−ai,要保证
b
j
b_j
bj后面的数均大于
a
i
a_i
ai后面的数,所以考虑
j
j
j指针的维护问题。一个想法是双指针,但是不能保证要保证
b
j
b_j
bj后面的数均大于
a
i
a_i
ai后面的数,因为不能做到一一对应,其实维护
a
i
a_i
ai的后继对应的指针即可。
code:
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define LL long long
#define PII pair<int, int>
#define PDD pair<double,double>
using namespace std;
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
int T;
inline int read(){
int X=0; bool flag=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
if(flag) return X;
return ~(X-1);
}
int main(){
T = read();
while(T--)
{
int n = read();
vector<int> a(n);
vector<int> b(n);
for(int i = 0; i < n; i++)
a[i]=read();
for(int i=0;i<n;i++)
b[i]=read();
int j=0;
vector<int> dmax,dmin;
for(int i=0;i<n;i++)
{
while(b[j]<a[i] && j<n) j++;
dmin.pb(b[j]-a[i]);
}
j=n-1;
for(int i=n-1;i>=0;i--)
{
dmax.pb(b[j]-a[i]);
int x=lower_bound(b.begin(),b.end(),a[i])-b.begin();
if(x==i)
j=i-1;
}
reverse(dmax.begin(),dmax.end());
for(auto num:dmin) cout<<num<<' ';
cout<<'\n';
for(auto num:dmax) cout<<num<<' ';
cout<<'\n';
}
return 0;
}