一个有 n 个整数的数组 a,n是一个奇数。 每次可以选择数组里的一个元素 ai 并把这个元素加上 1。 在至多 k 次操作之后,数组的中位数最大能变成多少。 输入格式:多组输入 第一行两个整数 n,k(1≤n≤2×105,1≤k≤109)。 第二行 n 和整数 a1,a2,......,an。 输出格式:k 次操作后数组的中位数。 |
3 2
1 3 5
5
简单讲解
首先将数据读入nums[],排序后求得当前中位数的下标mid
因为一共可以加K,要求让nums[mid]最大
所有答案就是 "nums[mid]+k" ??? 显然是不对的!
因为当nums[mid] == nums[mid+1] 时候, 前者再加1,中位数就变了...
而我们要做的,就是一直填中位数的位置,只看位置不看数
所以我们要用一个数(文中为num),动态的记录:
nums[mid] == nums[mid+1] == .... == nums[mid+num] 的位置
核心思想
只要让判断
nums[mid]+z == nums[mid+1]+z==...==nums[mid+num]+z == nums[mid+num+1]
且 k >= z*num ,我们就可把mid位置的高度同步到nums[mid+num+1]的高度
即此时 k-=z*num,num++;
当 k < z*num时,那么nums[mid]最终的值就是 当前nums[mid]+=k/num
#include
long long nums[100001];
int n,k;
void OP();
int main()
{while (scanf("%d %d",&n,&k)!=EOF) OP();return 0;
}
void OP()
{for(int z=0;z1){flag /= 2;for(int z=0;z=0){if(key=(nums[mid+num]-nums[mid])*num){k -= (nums[mid+num]-nums[mid])*num;nums[mid] = nums[mid+num];num++;}printf("%lld\n",nums[mid]+k/num);
}