二分2——2021-02-02更

二分2

T1 A-B问题

题目:

现有 n 个从小到大排列的整数,现在给你一个数 c, 要你在这 n 个数中找出两个数 a 和 b,使得 a-b=c ,请你计算出这样的方案有多少种?

输入
第一行2个正整数:n,c。(1<=n<=10^5,0<=c<= 10^9)
第二行包含n个空格隔开的整数ai。(0<=ai<=10^9)

输出
一个整数,表示该串数中包含的所有满足A-B=C的数对的方案数。

输入样例
5 2
2 2 4 8 10

输出样例
3

思路:

这道题目说的是要求出能满足A-B=C的对数,所以每次都要用二分来找当前这个数是否有与之差为m的数字,如果有,还得找出它的个数,所以需要两个二分,一个二分找是否有和现在这个数差为m的数,另一个用来找这个数的个数。
PS:补充两个系统二分查找函数

lower_bound(范围起点,范围终点,x)-范围:寻找给出的范围中大于或等于x的首个数字的序号,如果没有,则会输出范围终点+1;

upper_bound(范围起点,范围终点,x)-范围:寻找范围中大于x的首个数字的序号,如果没有,则输出范围终点+1;

函数最后减去范围名称,是要求出这个数的相对地址。

相对地址的概念:打个比方:一个酒店的房间的房号是1024,那么要求出它的相对地址也就是它在这一层的编号,就要减去它所在的楼层,可得1024-1000=24(相对地址)。同理,一个数在数组中的编号原来是带有数组名称的,所以我要求得它的编号,就要把数组名称去掉,所以要减数组名称。

代码:

#include<bits/stdc++.h>
using namespace std;
long long n,a[100010],x,h;

int main()
{
    
    
	ios::sync_with_stdio(false);
	cin>>n>>x;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	for(int i=1;i<=n;i++)
	{
    
    
		long long p=lower_bound(a+i,a+1+n,a[i]+x)-a;
		long long q=upper_bound(a+i,a+1+n,a[i]+x)-a;
		h+=q-p;			
	}
	cout<<h;
	return 0;
} 

T2 母鸡下蛋

题目:

在鸡国中,MG是远近闻名的下蛋明星。
鸡国专供下蛋的 n 个鸡窝呈一字排列在鸡国的“下蛋中心”,从左到右依次编号为 1 到 n。每个鸡窝都有一个最大可下蛋的量,其中第 i 个鸡窝的最大可下蛋量为 ci。
有时候由于 MG 产量实在太大而无法在一个鸡窝中下完所有的蛋,不得不转移到隔壁的鸡窝继续下蛋,如果隔壁的鸡窝还是不能让它下完所有的蛋,则 MG 继续转移,直到下完所有的蛋, 或者向“下蛋中心”管理员投诉“鸡窝数量实在太少了,我一只鸡的下蛋量都装不下!”。
为了节省转移时所耗费的体力,请你编程帮助 MG 找若干个连续的鸡窝(个数尽量少),让它能下完所有的蛋。

输入
第 1 行输入两个整数 n 和 t,表示“下蛋中心”有 n 个可供下蛋的鸡窝,MG 一次总共要下 t 个鸡蛋。
(1<=n<=10^6, 1<=t<=10^8)
第 2 行 n 个正整数 ci,依次表示第 i 个鸡窝最大可下蛋量为 ci 个。(1<=ci<=10000)

输出
1 行,一个整数或一个单词。当输出整数时表示让 MG 下完所有的蛋至少需要几个连续的鸡窝。当 MG 用完所有的鸡窝都无法下完所有的蛋时,MG 表示非常愤怒, 输出单词“Angry”

输入样例
5 4
1 2 1 2 3

输出样例
2

思路:

做这道题目要用到另一种方法——尺取法

尺取法:复杂度为O(n)。一直将y加到大于n,可以求最短距离,而且方便快速,十分好用。(别问我为什么这么少,我理解完了只能领悟意思,不能用语言准确的描述出来用法,详见代码)

代码:

#include<bits/stdc++.h>
using namespace std;
long long n,a[1000010],s[1000010],x,k,lz=1e9;

int main()
{
    
    
	ios::sync_with_stdio(false);
	cin>>n>>x;
	for(int i=1;i<=n;i++)
	{
    
    
		cin>>a[i];
		s[i]=s[i-1]+a[i];
	}
	long long z=1,y=1;
	while(y<=n)
	{
    
    
		k+=a[y++];
		while(k>=x)
		{
    
    
			lz=min(lz,y-z);
			k-=a[z++];
		}
	}
	if(lz>n)
		cout<<"Angry";
	else
		cout<<lz;
	return 0;
} 

二分系列——二分1(二分模板)

猜你喜欢

转载自blog.csdn.net/SSL_wyd/article/details/113575959