度度熊很喜欢数组!! Input 输入的第一行有一个正整数 T ,代表接下来有几组测试数据。 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;
}