Codeforces Round #734 (Div. 3) 2021-7-24

Problem C: Wonderful Coloring - 2

题意:
输入一个一维数组,每一位上存一位数字代表方块种类,现在要对这些方块进行尽可能多的染色,共k种颜色,要求:每种颜色的方块数相等,每种颜色的所有方块种类需不同,以1 ~ k代表k种颜色,打印出染完色后每个方块的颜色

知识点:
模拟、结构体

题解:
构造一个结构体,以储存每个方块的颜色,起始顺序,种类。首先统计每个种类的数量,将其中数量大于k的方块多出的个数的种类变为0,再将整个数组按照方块的编号进行排序,再将不能被整除的余数个方块的编号变为0,遍历数组,将编号为0的方块不上色(= 0),之后每k次一个周期对方块上色,最后按方块的初始顺序重新排序并输出。

代码:

#include <bits/stdc++.h>
 
using namespace std;
 
struct Dat
{
	int num;
	int col;
	int ans;
}dat[200010];
 
bool cmp1(Dat A, Dat B)
{
	return A.ans < B.ans;
}
bool cmp2(Dat A, Dat B)
{
	return A.num < B.num;
}	
 
int n, k, N;
int a[200010];
int cnt[200010];
 
void solve()
{
	cin >> n >> k;
	
	// 保存n值便于计算余数
	N = n;   
	
	for(int i = 1; i <= n; i ++ )
	{
		scanf("%d", &a[i]);
		
		// 序号和编号赋值 
		dat[i].num = i;
		dat[i].ans = a[i];
		
		// 记录编号出现次数 
		cnt[a[i]] ++;
		
		// 编号次数超出k次的都将编号变为0 
		if(cnt[a[i]] > k)
		{
			dat[i].ans = 0;
			N --;
		}
	}
	
	// 一轮排序(编号) 
	sort(dat + 1, dat + n + 1, cmp1);
 
	int temp = N % k; // 求出余数 
	
	int res = 1; // 颜色种类从1开始遍历 
	
	
	for(int i = 1; i <= n; i ++ )
	{
		// 编号为0不上色 
		if(dat[i].ans == 0)
		{
			dat[i].col = 0;
			continue;
		}
		
		// 多出来的数也不上色 
		if(temp > 0)
		{
			dat[i].col = 0;
			temp --;
			continue;
		}
		
		// 循环上色 
		if(dat[i].ans != 0)	dat[i].col += res;
		
		// 颜色每k次一周期 
		res ++;
		if(res == k + 1) res = 1;
	}
	
	// 重新排序(序号) 
	sort(dat + 1, dat + n + 1, cmp2);
	
	// 输出 
	for(int i = 1; i <= n; i ++ ) cout << dat[i].col << " ";
	cout << endl;
	
	// 初始化 
	memset(cnt, 0, sizeof(cnt));
	for(int i = 1; i <= n; i ++ ) dat[i].col = 0;
	res = 1;
}
 
int main()
{
	int T;
	cin >> T;
	while(T -- ) solve();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pale_B

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值