20200503二分法总结

首先,使用二分法的一个重要前提就是有序性。我们也可以利用二分法进行快速排序,二分法的时间复杂度为O(logn)

void qsort(int left,int right)
{
    int i=left,j=right,mid=a[(left+right)/2];
    while(i<=j)
    {
        while(a[i]<mid) i++;//在左边找大于等于mid的数
        while(a[j]>mid) j++;//在右边找小于等于mid的数
        if(i<=j)
        {
            swap(a[i],a[j]);//交换
            i++,j--;//继续找
        }
    }
    if(left<j) qsort(left,j);
    if(i<right) qsort(i,right);
}

二分法固定套路

function binarySearch(arr,key){
	int low=0; //数组最小索引值
	int high=arr.length-1; //数组最大索引值
	while(low<=high){
		int mid=Math.floor((low+high)/2);
		if(key==arr[mid]){
			return mid;
		}else if(key>arr[mid]){
			low=mid+1;
		}else{
			high=mid-1;
		}
	}
	return -1; //low>high的情况,这种情况下key的值大于arr中最大的元素值或者key的值小于arr中最小的元素值
}

同时插入一下分治算法的归并排序

void merge_sort(int *A,int x,int y,int *T)
{
   if(y-x>1)
   {
       int m=x+(y-x)/2;    //划分
       int p=x,q=m,i=x;
       merge_sort(A,x,m,T);    //递归求解
       merge_sort(A,m,y,T);    //递归求解
       while(p<m||q>y)
       {
           if(q>=y||(p<m&&A[p]<=A[q]))
               T[i++]=A[p++];    //从左半数组复制到临时空间
           else T[i++]=A[q++];    //从右半数组复制到临时空间
       }
       for(i=x;i<y;i++) A[i]=T[i];    //从辅助空间复制回原数组
   }
}

三分法可以用于求凸性或凹形函数的凸点或凹点
通过不断缩小 [L,R] 的范围,无限逼近所求点

double three_devide(double low,double up)  
{  
    double m1,m2;  
    while(up-low>=eps)  
    {  
        m1=low+(up-low)/3;  
        m2=up-(up-low)/3;  
        if(f(m1)<=f(m2))  
            low=m1;  
        else  
            up=m2;  
    }  
    return (m1+m2)/2;  
}  

1.4 Values whose Sum is 0
The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute how many quadruplet (a, b, c, d ) ∈ A x B x C x D are such that a + b + c + d = 0 . In the following, we assume that all lists have the same size n .
Input
The first line of the input file contains the size of the lists n (this value can be as large as 4000). We then have n lines containing four integer values (with absolute value as large as 2 28 ) that belong respectively to A, B, C and D .
Output
For each input file, your program has to write the number quadruplets whose sum is zero.
Sample Input
6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45
Sample Output
5
Hint
Sample Explanation: Indeed, the sum of the five following quadruplets is zero: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).
题意大概就是给出一个n表示有多少行数字,每行四个数字,表示分别是A B C D四个集合中各一个,问:从 A B C D四个集合中各拿出一个数字,加起来为0,共有多少种情况。
我觉得纯枚举的话,也就是写四层循环一定会超时的,只能进行分开查找的,可以用二分法,把四个集合分成两个,把这两个集合的每个元素都分别相加,而到一个很大的集合,在枚举剩下的两个集合的和,这样时间复杂度就降低很多了。

此外,在这里简单介绍一下lower_bound( )和upper_bound( ),二者都是利用二分查找的方法在从小到大的排序数组中进行查找的。

lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
AC代码

#include<iostream>  
#include<cstdio>  
#include<algorithm>  
using namespace std;  
const int maxn=4005;
#define ll long long 
ll sum[maxn*maxn];
ll A[4500],B[4500],C[4500],D[4500];
int n,m;
int main()
{
	while(~scanf("%d",&n))
	{
		m=0;
		for(int i=0;i<n;i++)
		scanf("%lld %lld %lld %lld",&A[i],&B[i],&C[i],&D[i]);
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
			sum[m++]=A[i]+B[j];
		sort(sum,sum+m);
		int cnt=0;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n;j++)
			{
			   int term=C[i]+D[j];
			   cnt+=upper_bound(sum,sum+m,-term)-lower_bound(sum,sum+m,-term);
			}
		}
		printf("%d\n",cnt);
	}
	return 0;
}

2.Median
Given N numbers, X1, X2, … , XN, let us calculate the difference of every pair of numbers: ∣Xi - Xj∣ (1 ≤ i < j ≤ N). We can get C(N,2) differences through this work, and now your task is to find the median of the differences as quickly as you can!

Note in this problem, the median is defined as the (m/2)-th smallest number if m,the amount of the differences, is even. For example, you have to find the third smallest one in the case of m = 6.

Input
The input consists of several test cases.
In each test case, N will be given in the first line. Then N numbers are given, representing X1, X2, … , XN, ( Xi ≤ 1,000,000,000 3 ≤ N ≤ 1,00,000 )

Output
For each test case, output the median in a separate line.

Sample Input
4
1 3 2 4
3
1 10 2
Sample Output
1
8
本题题意大概是题目给出一个数组,让数组中每两个数相减取绝对值,求所有绝对值组成的数组的中数
本题和上题类似,因为题目要求中数,判断小于等于mid的数是否大于所有绝对值个数的一半,所以需要用到lower_bound( )和upper_bound( ),其余地方没有什么特别之处,直接二分法固定套路即可。
AC代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#define MT(a,b) memset(a,0,sizeof(a))
#define ll long long
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int n,m;
 
 
bool solve(int x)
{
    int sum=0;
    for(int i=0;i<n-1;i++)
    {
        int p=upper_bound(a,a+n,a[i]+x)-a;
        sum+=p-i-1;
    }
    return sum>=(m+1)/2;
}
 
 
int main()
{
    while(cin>>n)
    {
        for(int i=0;i<n;i++)scanf("%d",&a[i]);
        sort(a,a+n);
        m=n*(n-1)/2;
        int l=0,r=a[n-1]-a[0],ans=(l+r)/2;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(solve(mid)) ans=mid,r=mid-1;
            else l=mid+1;
        }
        cout<<ans<<endl;
    }
    return 0;
}

3.Aggressive cows
Description

Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are located along a straight line at positions x1,…,xN (0 <= xi <= 1,000,000,000).

His C (2 <= C <= N) cows don’t like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?
Input

  • Line 1: Two space-separated integers: N and C

  • Lines 2…N+1: Line i+1 contains an integer stall location, xi
    Output

  • Line 1: One integer: the largest minimum distance
    Sample Input

5 3
1
2
8
4
9
Sample Output

3
Hint

OUTPUT DETAILS:

FJ can put his 3 cows in the stalls at positions 1, 4 and 8, resulting in a minimum distance of 3.

Huge input data,scanf is recommended.
大致题意:农夫有N间牛舍,牛舍排在一条线上,第i号牛舍在xi的位置。他的小牛彼此之间都会互相攻击。农夫决定要把每头牛都放在离其他牛尽可能远的牛舍,这样可以防止牛之间互相伤害。牛的数量是C,会给出n间牛舍的位置。

我们要使每两个牛的距离尽可能大,然后找出离得最近的两头牛之间的距离。

本题可以用二分+贪心来做。二分法预测距离,然后用cnt来记录匹配到槽的奶牛数先将第一头奶牛放在第一个槽,然后依次枚举每个槽,当枚举的槽与前一个放奶牛的槽的距离>=猜的答案时,cnt++,最后如果cnt>=牛的数量,说明这个距离可行,如果cnt<牛的数量,说明这个距离过大。
下面上代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,c;
long long a[100007];
bool solve(long long mid)
{
	int cnt=1;      
	int crw=a[0];  
	for(int i=1;i<n;i++)
	{
		if(a[i]-crw>=mid) 
		{
			cnt++;
			crw=a[i];
		}
		if(cnt>=c)return true;
	}
	return false;

}
int main()
{
	scanf("%d%d",&n,&c);
	for(int i=0;i<n;i++)
	  scanf("%lld",&a[i]);
	sort(a,a+n);
	long long left=a[0],right=a[n-1];
	while(right-left>1)
	{
		long long mid=(left+right)/2;
		if(solve(mid))left=mid;
		else right=mid;
	}
	printf("%lld\n",left);
	return 0;
}

4.River Hopscotch
Every year the cows hold an event featuring a peculiar version of hopscotch that involves carefully jumping from rock to rock in a river. The excitement takes place on a long, straight river with a rock at the start and another rock at the end, L units away from the start (1 ≤ L ≤ 1,000,000,000). Along the river between the starting and ending rocks, N (0 ≤ N ≤ 50,000) more rocks appear, each at an integral distance Di from the start (0 < Di < L).

To play the game, each cow in turn starts at the starting rock and tries to reach the finish at the ending rock, jumping only from rock to rock. Of course, less agile cows never make it to the final rock, ending up instead in the river.

Farmer John is proud of his cows and watches this event each year. But as time goes by, he tires of watching the timid cows of the other farmers limp across the short distances between rocks placed too closely together. He plans to remove several rocks in order to increase the shortest distance a cow will have to jump to reach the end. He knows he cannot remove the starting and ending rocks, but he calculates that he has enough resources to remove up to M rocks (0 ≤ M ≤ N).

FJ wants to know exactly how much he can increase the shortest distance before he starts removing the rocks. Help Farmer John determine the greatest possible shortest distance a cow has to jump after removing the optimal set of M rocks.

Input
Line 1: Three space-separated integers: L, N, and M
Lines 2… N+1: Each line contains a single integer indicating how far some rock is away from the starting rock. No two rocks share the same position.
Output
Line 1: A single integer that is the maximum of the shortest distance a cow has to jump after removing M rocks
Sample Input
25 5 2
2
14
11
21
17
Sample Output
4
Hint
Before removing any rocks, the shortest jump was a jump of 2 from 0 (the start) to 2. After removing the rocks at 2 and 14, the shortest required jump is a jump of 4 (from 17 to 21 or from 21 to 25).
大致题意:给出一条河的长度n米,给出石头的块数m块,需要去除k块石头,使得那时的最短距离尽可能大,输出那个最短距离。
解题思路:取得石块间的最大距离与最小距离,则移除石头后的最短距离必然在二者之间,此时我们就可以再这个区间内对结果进行二分,看二分出的最短距离是否能符合移除m个石头的方案即可

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
using namespace std;
long long a[50010],l,m,n;
int main()
{
	long long i,j,low=0,high,mid;
	while(scanf("%lld %lld %lld",&l,&n,&m)!=EOF){
			a[0]=0;
			for(i=1;i<=n;i++)
			{
				scanf("%d",&a[i]);
			}
			high=l;
			low=0;
			sort(a,a+n+1);
			while(low<=high){
	            mid=(low+high)/2;
	            long long num=0,last=0;
	            for(i=1;i<=n;i++)
	            {
	                if(a[i]-last<mid) num++;
	                else last=a[i];
	            }
	            if(num<=m) low=mid+1;
	            else high=mid-1;

            }
       		printf("%d\n",high);
	}
	return 0;
 }

5.Cable master
Inhabitants of the Wonderland have decided to hold a regional programming contest. The Judging Committee has volunteered and has promised to organize the most honest contest ever. It was decided to connect computers for the contestants using a “star” topology - i.e. connect them all to a single central hub. To organize a truly honest contest, the Head of the Judging Committee has decreed to place all contestants evenly around the hub on an equal distance from it.
To buy network cables, the Judging Committee has contacted a local network solutions provider with a request to sell for them a specified number of cables with equal lengths. The Judging Committee wants the cables to be as long as possible to sit contestants as far from each other as possible.
The Cable Master of the company was assigned to the task. He knows the length of each cable in the stock up to a centimeter,and he can cut them with a centimeter precision being told the length of the pieces he must cut. However, this time, the length is not known and the Cable Master is completely puzzled.
You are to help the Cable Master, by writing a program that will determine the maximal possible length of a cable piece that can be cut from the cables in the stock, to get the specified number of pieces.
Input
The first line of the input file contains two integer numb ers N and K, separated by a space. N (1 = N = 10000) is the number of cables in the stock, and K (1 = K = 10000) is the number of requested pieces. The first line is followed by N lines with one number per line, that specify the length of each cable in the stock in meters. All cables are at least 1 meter and at most 100 kilometers in length. All lengths in the input file are written with a centimeter precision, with exactly two digits after a decimal point.
Output
Write to the output file the maximal length (in meters) of the pieces that Cable Master may cut from the cables in the stock to get the requested number of pieces. The number must be written with a centimeter precision, with exactly two digits after a decimal point.
If it is not possible to cut the requested number of pieces each one being at least one centimeter long, then the output file must contain the single number “0.00” (without quotes).
Sample Input
4 11
8.02
7.43
4.57
5.39
Sample Output
2.00
大致题意:题意:有n段长度分别为Li的电缆,要求把它们分割成K条长度为X的电缆,问X的最大值为多少。
将X视为变量,可知它的范围为0~0x3f3f3f3f; 题目即为求电缆长度取X时,所得的电缆条数与K的大小关系问题。 用二分查找法能很快的找出K的值,不过要注意精度,一定要向下取整
这个题WA了五次,刚开始是因为精度设置错了,设置的high-low>0.01,其实应该设置为0.001,其次是子函数返回值类型刚开始设置的也有问题,刚开始设置的为double类型,但实际上返回值为段数,不可能为小数,必定为整数,下面附上AC代码

#include <iostream>
#include <algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define N 10005
#define INF 100001
using namespace std;
double a[N];
int n,k;
bool solve(double x)
{
	int num=0,i;
	for(i=0;i<n;++i)
		num+=(int)(a[i]/x);
	return num>=k;
}
 int main()
{
	while(scanf("%d%d",&n,&k)!=EOF)
	{
		int i;
		for(i=0;i<n;++i)
			scanf("%lf",&a[i]);
		double left=0,right=INF,mid;
		i=1000;
		while(i--)
		{
			mid=(left+right)/2;
			if(solve(mid))
				left=mid;
			else
				right=mid;
		}
		printf("%0.2f\n",floor(right*100)/100);
	}
	return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值