二分查找习题

度度熊很喜欢数组!! 

我们称一个整数数组为稳定的,若且唯若其同时符合以下两个条件: 

1. 数组里面的元素都是非负整数。 
2. 数组里面最大的元素跟最小的元素的差值不超过 11。

举例而言,[1,2,1,2][1,2,1,2] 是稳定的,而 [−1,0,−1][−1,0,−1] 跟 [1,2,3][1,2,3] 都不是。 

现在,定义一个在整数数组进行的操作: 

* 选择数组中两个不同的元素 aa 以及 bb,将 aa 减去 22,以及将 bb 加上 11。 

举例而言,[1,2,3][1,2,3] 经过一次操作后,有可能变为 [−1,2,4][−1,2,4] 或 [2,2,1][2,2,1]。 

现在给定一个整数数组,在任意进行操作后,请问在所有可能达到的稳定数组中,拥有最大的『数组中的最小值』的那些数组,此值是多少呢? 

Input

输入的第一行有一个正整数 TT,代表接下来有几组测试数据。 

对于每组测试数据: 
第一行有一个正整数 NN。 
接下来的一行有 NN 个非负整数 xixi,代表给定的数组。

* 1≤N≤3×1051≤N≤3×105 
* 0≤xi≤1080≤xi≤108 
* 1≤T≤181≤T≤18 
* 至多 11 组测试数据中的 N>30000N>30000

Output

对于每一组测试数据,请依序各自在一行内输出一个整数,代表可能到达的平衡状态中最大的『数组中的最小值』,如果无法达成平衡状态,则输出 −1−1。

Sample Input

2
3
1 2 4
2
0 100000000

Sample Output

2
33333333

这道题一开始题意都理解不好,尤其是那个“代表可能到达的平衡状态中最大的『数组中的最小值』”,这么绕口。。。
好了,不吐槽了

其实就是让你找平衡状态时,数组中的最小值,达到平衡时数组中也就俩数,因为要保证最大值最小值之差小于1

解题的思路是这样的,总体上是用的二分法,先找出数组中的中间值,接着遍历数组中的每个元素,如果小于数组,x加上这个差,如果大于数组,y加上这个差的一半;最后比较这两个数的大小,就是二分的步骤。

大概就是这样,要加把劲了

补充一个小知识点:
关于%I64d和%lld的问题
两种都是C语言中格式化输出64位整型的正确做法。
区别在于编译器不同。
gcc(mingw32),g++(mingw32)只支持%I64d的输出方式。 
gcc(linux i386),g++(linux i386)只支持%lld的输出方式。
另外,mac上的gcc/g++不支持%I64d的方式。

最后把代码码一遍吧
 


#include<iostream>
#include<stdio.h>
#define maxn 300010
#define LL long long
LL a[maxn];
using namespace std;

int main(){
    int N;
    cin>>N;
    while(N--){
    	LL T;
		cin>>T;
		for(int i=0;i<T;i++){
			cin>>a[i];
		} 
		LL mid;
		LL l=0;
		LL r=0;
		while(l+1<r){
			l=a[0];
			r=a[0];
			for(int i=0;i<T;i++){
				if(l>a[i]){
					l=a[i];
				}
				if(r<a[i]){
					r=a[i];
				}
			}
			mid=(l+r)/2;
			LL x=0;
			LL y=0;
			for(int i=0;i<T;i++){
				if(a[i]<mid){
					x+=mid-a[i];
				}else{
					y+=(a[i]-mid)/(LL)2;
				}
			}
			if(x>=y){
				l=mid;
			}else{
				r=mid;
			}
		}
		printf("%l64d",l);
    }
    
}

猜你喜欢

转载自blog.csdn.net/Helloirbd/article/details/81744156