F. Honk's pool(map+思维)

在这里插入图片描述在这里插入图片描述在这里插入图片描述
这道题题意很简单:就是一次操作:把最大的-1,最小的+1,问经过k次操作之后最大-最小值是多少,就OK了;
但是怎么写呢?我刚开始想用set来写,不断模拟这个方法,但是一看k是1e9,所以这个想法取消了;
之后我队友写出来了;
他说可以根据k值整体+,-;
然后我想了一下这个东东:
在这里插入图片描述
用一个map记录每个 数字出现的次数;
如果脑袋灵活的,应该可以知道这个:如果我k=2;那么对应的map[5]是不是就应该直接都向下-1;并且map[1]是不是直接向上+1;
所以他们不断向中间靠拢;
然后原来的map[5]就应该变为0,map[1]也是;所以可以发现这个可以整体+1或者-1;同时,向下的区间和向上的区间对应个数++;然后判断是不是这个对应的map值为0,如果左边为0那么就l++,如果右边为0就r–;
对于最后结束的条件;可以知道:
比如2 2 2 2 那么k不管是多少次那么max-min==0;然后还有这种5 6那么不管k为多少,差值一直都是1了,所以循环到这两种情况就可以break了;
AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,k,a[500050];
	unordered_map<int,int> mm;
int main(){
	while(~scanf("%d %d",&n,&k)){
	for(int i=0;i<n;i++){
		 scanf("%d",&a[i]);
		 mm[a[i]]++;
	}
	sort(a,a+n);//排序 
	int left=a[0],right=a[n-1];
	while(k>0){
		int t=min(min(mm[left],mm[right]),k);//取最小的,因为是整体改变 
		k-=t;//k消耗的次数 
		mm[left]-=t;//左边变的个数 
		mm[right]-=t;//右边变的个数 
		mm[left+1]+=t;//左边整体+1,使得left+1的个数增加t个 
		mm[right-1]+=t;//右边整体-1,使得right-1的个个数+t个 
		if(!mm[left])left++;//如果这个给变没有了,那么就指向右边一个数字 
		if(!mm[right])right--;//如果这个给变没有了,那么就指向左边一个数字 
		if(right-left==1||right-left==0)break;//这就是最坏的情况下,跳出,因为如果这里结束循环,那么说明后面剩余的k次 不管怎么变也只能是这两个值中的一个 
	}
	cout<<right-left<<endl;//输出答案 
	mm.clear();//注意清0 
}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值