ABC 313 C - Approximate Equalization 2

文章介绍了两种C++编程方法解决一个关于序列操作的问题,即通过最少的加减操作使序列中任意两项的差不大于1。第一种方法计算平均值后调整,第二种方法使用两个计数器分别记录需要填入小平均值和砍到大平均值的数。
摘要由CSDN通过智能技术生成

题目解析:

有一个序列A(a1,a2,a3......an),你可以进行以下操作:

选两个数ai, aj  (1 <= i, j <= n)ai+1,aj-1

问至少进行多少次操作,可以使A序列中任意两项的差不大于1


方法一(写博客的时候想到的......):

算出平均值,与每一位求差。把差除以2,得到答案。

原理:

因为每次操作是把两个数,一个加一,一个减一。所以从数字上来讲,只是进行了一次搬运量为1的数字搬运。所以只要把每一位的值填到平均值,或是砍到平均值就可以了。

但是会有问题,因为不一定必须到平均值,所以会有多算的部分。不能拿全分,可以骗点。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 10;
int n, a[MAXN];
long long sum, ans;
int main()
{
	cin >> n;
	for (int i = 1; i <= n; ++ i)
	{
		cin >> a[i];
		sum += a[i];  //求和
	}
	sum /= n;  //算平均值
	for (int i = 1; i <= n; ++ i)
		ans = ans + abs(sum - a[i]);  //求差
	ans /= 2;
	cout << ans << endl;
	return 0;
} 

方法二:

方法一虽然有问题,但不妨是一种思路。

我们只需要改一些地方,就可以满分。

求平均值,一个是 sum/n 直接求的,

另一个是前面的值加一。

因为会有一些数不用砍到最低的平均值。典型样例:

3
3 3 5
//只要砍到4, 但程序算的是3.能对只是巧合。

在用两个计数器。一个记录需要填到小平均值的数,一个记录需要砍到大平均值的数。

最后取较大的数。毕竟你不能为了少操作,不把别人变成平均值,使其不满足题意。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=2e5+5;
int N, a[maxn], c, d, d2, e, e2;
signed main(){
	cin >> N;
	for(int i = 1; i <= N; i ++)
	{
		cin >> a[i];
		c += a[i];
	}
	d = c / N;
	if(c % N == 0) d2=d;
	else d2 = d + 1;
	for(int i = 1; i <= N; i ++)
	{
		if(a[i] < d)
			e += d - a[i];
		if(a[i] >= d2)
			e2 += a[i] - d2;	
	}
	cout << max(e,e2) << endl;
	return 0;
}

如果觉得看懂了,点个赞吧!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值