Codeforces Round #734 (Div. 3)题解

B2. Wonderful Coloring - 2

题目的基本意思:
1:每个元素要么不涂,要么只能涂一种颜色;
2:每一种颜色涂的元素两两都是不相同的;
3:每一种颜色涂的元素的个数时相同的;
4:最后序列中涂的元素的个数要最大;

解题的思路:
1:去掉没必要涂的元素
(1)该元素在序列中的个数要大于k(k表示颜色的总数),将超过k的那部分直接用0表示即可,不用涂;可以考虑先把每个元素出现前k次的保存在vector数组q中。

2:为了保证每一种颜色涂的元素的个数时相同的,所以最后涂的元素的总个数一定是k的整数倍,所以存在q中的元素的总数不能整除k时,考虑删除多余的元素知道可以整除k为止,这样也可以保证最后序列中涂的元素的个数要最大。

3:每一种颜色涂的元素两两都是不相同的,考虑将元素的大小进行排序,为了保证输出的时候还是原来的顺序,我们不改变元素本身的顺序,而是将他们的下标改变顺序,就是元素本身大的他的下标就在前面。最后ans数组就是用来保存答案,依次从q的前后用1 2 3……k 1 2……来涂色;

4:注意数组的初始化为0;

样例模拟

input(随便模拟一个)
11 3(11个元素,上3中颜色)
3 1 1 1 1 10 3 4 10 2 10

数组名称里面的值(下标从0开始)
a[]3 1 1 1 1 10 3 4 10 2 10
q 里面的元素为a中所选元素的下标0 1 2 3 4 5 6 7 8 9 10 //有4个1,最后一个1不选
q 里面的元素为a中所选元素的下标0 1 2 3 5 6 7 8 9 10 //由于元素的总数要能整除k,所以只能有9个元素
q 里面的元素对应a[]中对应的值3 1 1 1 10 3 4 10 2 //由于1的个数有4个,当我们只能保存3个
排序后的q1 2 3 9 0 6 7 5 8 //根据上一行排序而来
ans[]ans[1]=1,ans[2]=2,ans[3]=3
ans[]ans[1]=1,ans[2]=2,ans[3]=3,ans[9]=1,ans[0]=2,ans[6]=3
ans[]ans[1]=1,ans[2]=2,ans[3]=3,ans[9]=1,ans[0]=2,ans[6]=3,ans[7]=1,ans[5]=2,ans[8]=3

AC代码

(由于数组的初始化,时间用了850ms)

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

const int N = 2e5 + 10;
int a[N], ha[N];

int ans[N];

bool cmp(int i, int j) {
	return a[i]<a[j];
}

int main() {
	int t;
	cin >> t;
	while (t--) {
		int n, k;
		cin >> n >> k;
		vector<int> q;
		memset(ha, 0, sizeof(ha));
		memset(a, 0, sizeof(a));
		memset(ans, 0, sizeof(ans));
		for (int i = 0; i < n; i++) {
			cin >> a[i];
			ha[a[i]]++;
			if (ha[a[i]] <= k)q.push_back(i);
		}
		while (q.size() % k != 0)q.pop_back();
		sort(q.begin(), q.end(), cmp);
		for (int i = 0; i < q.size(); i++) {
			ans[q[i]] = i % k + 1;
		}
		for (int i = 0; i < n; i++)
			cout << ans[i] << " ";
		cout << endl;
	}
	return 0;
}

小优化(为了不每一次操作都要初始化,我可以全部弄成vector数组)

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

//const int N = 2e5 + 10;
//int a[N], ha[N];
//
//int ans[N];

//bool cmp(int i, int j) {
//	return a[i]<a[j];
//}

int main() {
	int t;
	cin >> t;
	while (t--) {
		int n, k;
		cin >> n >> k;
		**vector<int> q, a(n+10), ha(n + 10), ans(n+10);**
		for (int i = 0; i < n; i++) {
			cin >> a[i];
			ha[a[i]]++;
			if (ha[a[i]] <= k)q.push_back(i);
		}
		while (q.size() % k != 0)q.pop_back();
		sort(q.begin(), q.end(), [&](int i, int j) {return a[i] < a[j]; });
		for (int i = 0; i < q.size(); i++) {
			ans[q[i]] = i % k + 1;
		}
		for (int i = 0; i < n; i++)
			cout << ans[i] << " ";
		cout << endl;
	}
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

米兰的小码匠

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

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

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

打赏作者

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

抵扣说明:

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

余额充值