【习题总结】二分查找与二分答案

二分查找

  二分查找,即查询有序数组中某个数的前驱/后继,为了偷懒 ,我们一般用:

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 bjai,要保证 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值