原题:
You are given an array a of n integers, where n is odd. You can make the following operation with it:
Choose one of the elements of the array (for example ai) and increase it by 1 (that is, replace it with ai+1).
You want to make the median of the array the largest possible using at most k operations.
The median of the odd-sized array is the middle element after the array is sorted in non-decreasing order. For example, the median of the array [1,5,2,3,5] is 3.
题意:
给n(n为奇数)个数,和k个加一的机会,问操作后数组中位数是多少。
标签:二分搜索(binary search)、贪心、数学、排序
思路:
我在考场上想的是模拟,从小到大排序,从中间这个数往上加,如果和下一个数相等了,就令下一个数加一,依次类推,用了递归。然而TLE。
很显然为了使中位数最大,在n/2+1之前的数是不会考虑添加了。 下面贴一个AC代码:
该代码思路:
以原有中值x为下限,x+k为上限进行二分搜索。复杂度:O((n/2)⋅log(109))
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;//有的数据比较大,用ll
ll n, k;
ll x;
vector < ll > a;
bool check(ll x)
{
ll moves=0;
for (int i=n/2; i<n; i++)
{
if (x-a[i]>0) moves+=x-a[i];
if (moves>k) return false;
}
if (moves<=k) return true;
else return false;
}
int main()
{
ios_base::sync_with_stdio(false);
cin>>n>>k;
for (int i=1; i<=n; i++)
{
cin>>x;
a.push_back(x);
}
sort(a.begin(), a.end());
ll small=1;
ll big=2000000000;
while (small!=big)
{
ll mid=(small+big+1)/2;
if (check(mid))
{
small=mid;
}
else{
big=mid-1;
}
}
cout<<small;
}
我的TLE代码:(估计要用二分搜索优化)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
long long int a[20010];
long long int n,m,t=1;
long long int k;
int _add(int j);
int main()
{
scanf("%lld%lld",&n,&k);
m=n/2;
for(int i=0;i<n;i++)
scanf("%lld",&a[i]);
sort(a,a+n);
if(n==1)
{
cout<<a[0]+k;
return 0;
}
//11112
//for(int i=0;i<n;i++)
//cout<<a[i];
while(k)
{
_add(t);
}
cout<<a[m];
}
int _add(int j)//a[2]=1;a[3]=1;a[4]=2
{
if(a[m+j]==a[m]&&m+j+1!=n)//
{
t++;//t=2
return 0;
}
if(a[m+j]==a[m]&&m+j+1==n)
{
a[m]+=k/(j+1);
k=0;
return 0;
}
if(k>=(a[m+j]-a[m])*j)//5>2
{ k-=((a[m+j]-a[m])*j);//k=3
a[m]=a[m+j];//a[2]=2
}
else
{
a[m]+=k/(j+1);
k=0;
}
if(m+j+1!=n)t++;//t=3!
return 0;
}