这道题,我一读很懵逼,我还以为是周期,结果队友给我解释了一下,居然可以用这么简单的方法来搞定;厉害我的队友!!(网上的二分我是真没明白QAQ)
首先来理解这道题吧:
题意:求对数组中任意元素经过K次操作(每次+1)之后排序,使得中位数最大,求这个最大的中位数是多少;
这道题,可以这样理解(把数字抽象成几何形状):
然后我们可以很清楚的知道:最优的选择肯定是每次填中间的数(因为如果你填后面的数,那中间的数还是中位数,不是吗?);那么如果中间的填满了就应该填第5个数,一次类推,我们可以知道一个细节,就是每次填中间的数时到了和它的右边的数相等的时候,那么按理说就应该是一起填上去,根据这个思路就知道如果,4,5填的一样多了,那么6就应该跟着走;
根据这个思路我可以发现:
那么如果所得到的和sum(就是每次需要一起升的高度的和(可以脑袋里面想一下))>k了那么就应该跳出循环;注意sum>k是sum有多余的一部分,所以多余的一部分应该减去,最后根据代码就可以理解了:(注意ll)
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
int main(){
ll n,k,a[maxn];
scanf("%lld %lld",&n,&k);
for(int i=0;i<n;i++)scanf("%lld",a+i);
sort(a,a+n);
ll mid=n/2,sum=0,z=1;
for(int i=mid+1;i<n;i++){
ll tt=(a[i]-a[i-1])*z;
sum+=tt;
if(sum>k){
sum-=tt;
break;
}
z++;
}
ll ans=a[mid+z-1/*这里是对z减的,因为要满足a[]的下标*/]+(k-sum)/z;//这里k-sum是多出来的,因为可以想象到,z个的时候就已经平了,
printf("%lld\n",ans);
return 0;
}