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;
}