2018百度之星初赛(B) 1004 p1m2(二分)

度度熊很喜欢数组!!

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

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

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

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

* 选择数组中两个不同的元素 a 以及 b ,将 a 减去 2 ,以及将 b 加上 1 。

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

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

 

Input

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

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

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

 

Output

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

 

Sample Input

 

2

3

1 2 4

2

0 100000000

 

Sample Output

 

2

33333333

思路:读完题首先想到的肯定是暴力模拟,但这是不可能的,限时1000ms,考虑一下题目中稳定的状态,会发现平衡状态是一定会存在的,而且成为平衡状态会反复操作数组各个元素(操作后数组最大/小值会变化),不要被局限在这个操作的实现上,而是应该注意始末状态的联系上:每2个元素都会被操作成差小于等于1的数,以操作次数为切题点感觉不靠谱,因为每个数被操作的次数是不相同的,那就考虑最终的数,最终的数一定小于(最大+最小)/2的,所以二分数值找整个数组增减次数相同的情况即为答案。

代码如下:

#include<set>
#include<map>
#include<list>
#include<deque>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ext/rope>
#include<iostream>
#include<algorithm>
#define pi acos(-1.0)
#define INF 0x3f3f3f3f
#define per(i,a,b) for(int i=a;i<=b;++i) 
using namespace std;
using namespace __gnu_cxx;
#define LL long long
const int maxn = 3e5 + 100;
LL a[maxn];
int main() 
{
    int t; 
	scanf("%d", &t);
    while(t--) 
	{
        int n;
        cin>>n;
        LL l,r;
        per(i,0,n-1) 
        scanf("%I64d",&a[i]);
        l=r=a[0];
        per(i,1,n-1)
        {
            if(a[i]<l) l=a[i];
            if(a[i]>r) r=a[i]; 
        }
        r++;
        while(l+1<r)
        {
            LL mid=(l+r)/2;
            LL x=0,y=0;
           per(i,0,n-1)
            {
				if(a[i]<mid) x+=mid-a[i];//小数加的次数 
                else if(a[i]>mid) y+=(a[i]-mid)/(LL)2;//大数减的次数 
            }
			if(y>=x) l=mid;
            else r=mid;
        }
        printf("%I64d\n",l);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/PleasantlY1/article/details/81625695