HDU 5353 Average(贪心)

36 篇文章 0 订阅
18 篇文章 0 订阅

Average

题解:首先如果总糖果数不能整除 n n n就输出 N O NO NO。其次考虑两个方向变为暂时只朝一个方向,每个人与平均值的差,如果比平均值少一就从后一个人那里拿一个,如果比平均值多一个就给后一个人一个,如果等于平均值就什么也不做。因此枚举左右方向两次,最后每次枚举模拟完判断一下是否最后平分了就可以了。

#include<bits/stdc++.h>
typedef long long LL;
#define P pair<int,int>
using namespace std;
int a[100100], b[100100], n;
vector< P > ans;
bool solve(int start,int d)
{
	ans.clear();
	memcpy(b,a,sizeof a);
	int f = 0;
	if(b[start] == 2) {
		int s = start, e = (s - d + n) % n;
		b[s]--, b[e]++;
		ans.push_back(P(s+1,e+1));
		f = 1;
	}
	for(int i = 0; i < n - f; ++i) {
		int s = (start + i * d + n) % n, e = (start + (1 + i) * d + n) % n;
		int diff = b[s];
		if(diff == 1) {
			ans.push_back(make_pair(s + 1, e + 1));
			b[s]--; b[e]++;
		}else if(diff == -1) {
			ans.push_back(make_pair(e + 1, s + 1));
			b[s]++; b[e]--; 
		}else if(diff == 0){
			continue;
		}else{
			return 0;
		}
	}
	for(int i = 0; i < n; ++i) if(b[i])  return 0;
	printf("YES\n%d\n", (int)ans.size());
	for(int i = 0; i < ans.size(); ++i) {
		printf("%d %d\n",ans[i].first, ans[i].second);
	}
	return 1;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
	int T;
	cin>>T;
	while(T--) {
		scanf("%d",&n);
		LL sum = 0;
		int max1 = 0, id = 0;
		for(int i = 0; i < n; ++i) {
			scanf("%d",a+i);
			sum += a[i];
		}
		if(sum % n != 0) {
			puts("NO");
			continue;
		}
		int av = sum / n, f = 1;
		for(int i = 0; i < n; ++i) a[i] -= av;
		for(int i = 0; i < n; ++i) {
			if(abs(a[i]) > 2 || (n == 2 && abs(a[0]) >= 2)) {
				puts("NO");
				f = 0;
				break;
			}
		}
		if(!f) continue;
		for(int i = 0; i < n; ++i) {
			if(a[i] > 0) { id = i; break; }
		}
		int ok = 1;
		if(!solve(id,1)) ok = solve(id,-1);		
		if(ok == 0) puts("NO");
	}
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值