洛谷 1109

模拟也能出奇迹

原题传送门

Description

有N组学生,给出初始时每组中的学生个数,再给出每组学生人数的上界R和下界L(L≤R),每次你可以在某组中选出一个学生把他安排到另外一组中,问最少要多少次才可以使N组学生的人数都在[L,R][L,R]中.

Data

Input
第一行一个整数N,表示学生组数; n≤50
第二行N个整数,表示每组的学生个数;
第三行两个整数 L,R,表示下界和上界.
Output
一个数,表示最少的交换次数,如果不能满足题目条件输出-1.

	Sample Input
	2
	10 20
	10 15
	Sample Output
	5

思路

用某奆的话说:

这道题,出乎意料的简单!

好像每个人都说过这句话 ?
好了开始正题:

铺垫

乍一看这道题可能难以下手,但是这可是[普及-]的难度啊!做不出来岂不是自损名声
于是可以仔细观察,为什么这道题难以下手
模拟学生的流动,可能会花费大量时间.
既要考虑人员流动最小,又要保证各组人员始终在[L,R]以内.
想想就麻烦(不做了)
但是,真的需要这样模拟吗?

接近

排座位的时候,需要按甲乙丙丁……
这个时候,所有人的都是有不同的.
换句话说,这是一个排列,是按 ABDEC… 这样的顺序安排的
但是本题的人员是“一视同仁”,都是 AAAAA…
所以,一定要考虑每个人?
想到这里,豁然开朗.

AC我来了!

预先规定:
我们把[N*L,N*R]之间的总和S成为合法总和

先判断不合法(-1)的情况:

  1. 当总和大于合法总和时,就是不合法的.
  2. 当总和小于合法总和时,就是不合法的

没错就是这么简单
可以反证,在这个总和区间 的都可以被分配好.
那么:我们可以对Ai 进行分析:

  1. 如果Ai 大于等于L且小于等于R, 不需要处理.
  2. 如果Ai大于R,那么因为总和S在合法总和区间内,所以总可以找到一种方案,使原本在[L,R]之间的Ai保持在[L,R]内,并且填补那些小于L的Ai.(比如直接填补)
  3. 如果Ai小于L,逻辑同2.
    所以,我们只需判断有多少个Ai>R,多少个Ai<L,然后将这些组数的总和比较,输出较大值即可.?

具体问题还需读者自行实现.

Code

int n;
int a[N];
int L,R,A,B,S;
int main()
{
	for (int i=1;i<=n;i++) S+=a[i];
	cin >>L>>R;
	for (int i=1;i<=n;i++)
		if (a[i]>R) A+=(a[i]-R);
		else if (a[i]<L) B+=(L-a[i]);
	if (S>R*n||S<L*n) cout<<"-1"<<endl;
	else cout<<max(A,B)<<endl;
}

感谢奆老关注qwq ?

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值