E. Colors and Intervals

题目:https://codeforces.com/contest/1552/problem/E

The numbers 1,2,…,n⋅k are colored with n colors. These colors are indexed by 1,2,…,n. For each 1≤i≤n, there are exactly k numbers colored with color i.

Let [a,b] denote the interval of integers between a and b inclusive, that is, the set {a,a+1,…,b}. You must choose n intervals [a1,b1],[a2,b2],…,[an,bn] such that:

for each 1≤i≤n, it holds 1≤ai<bi≤n⋅k;
for each 1≤i≤n, the numbers ai and bi are colored with color i;
each number 1≤x≤n⋅k belongs to at most ⌈nk−1⌉ intervals.
One can show that such a family of intervals always exists under the given constraints.

Input
The first line contains two integers n and k (1≤n≤100, 2≤k≤100) — the number of colors and the number of occurrences of each color.

The second line contains n⋅k integers c1,c2,…,cnk (1≤cj≤n), where cj is the color of number j. It is guaranteed that, for each 1≤i≤n, it holds cj=i for exactly k distinct indices j.

Output
Output n lines. The i-th line should contain the two integers ai and bi.

If there are multiple valid choices of the intervals, output any.

Examples
input
4 3
2 4 3 1 1 4 2 3 2 1 3 4
output
4 5
1 7
8 11
6 12
input
1 2
1 1
output
1 2
input
3 3
3 1 2 3 2 1 2 1 3
output
6 8
3 7
1 4
input
2 3
2 1 1 1 2 2
output
2 3
5 6
Note
In the first sample, each number can be contained in at most ⌈43−1⌉=2 intervals. The output is described by the following picture:

In the second sample, the only interval to be chosen is forced to be [1,2], and each number is indeed contained in at most ⌈12−1⌉=1 interval.

In the third sample, each number can be contained in at most ⌈33−1⌉=2 intervals. The output is described by the following picture:

解题思路:

We describe the algorithm and later we explain why the construction works.

Let xi,j (1≤i≤n, 1≤j≤k) denote the position of the j-th occurrence of color i (from the left).

First, sort the colors according to xi,2. Take the first ⌈nk−1⌉ colors, and to each of them assign the interval [xi,1,xi,2]. Then, sort the remaining colors according to xi,3, take the first ⌈nk−1⌉ and to each of them assign the interval [xi,2,xi,3].

More generally, in the t-th step: sort the remaining colors according to xi,t+1; take the first ⌈nk−1⌉ (possibly less in the last step) of these colors; assign to each color i the interval [xi,t,xi,t+1].

Let us show that this choice of intervals works. It is straightforward to see that the first two properties hold.

It remains to check the third property. We prove that two intervals selected in different steps are disjoint. Since in each step we select at most ⌈nk−1⌉ intervals, this is sufficient to conclude. Consider two colors i,j selected in two different steps s<t respectively. Then, we have xi,s+1<xj,s+1≤xj,t and thus [xi,s,xi,s+1]∩[xj,t,xj,t+1]=∅, which is exactly what we wanted to prove.

Complexity: O(nk).

AC代码:

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


void solve() {

	int n, k;
	cin >> n >> k;

	int r = (n + k - 2) / (k - 1); //隔间

	vector<int> c(n * k + 1);  //存n*k个数

	for (int i = 1; i <= n * k; i++) cin >> c[i];

	vector<vector<int>> x(n + 1);  //按数字分开

	for (int i = 1; i <= n * k; i++) {
		x[c[i]].push_back(i); //记录每个数字出现的下标
	}

	vector<int> colors(n); //颜色数
	iota(colors.begin(), colors.end(), 1); //赋值从1-n

	vector<pair<int, int>> intervals(n + 1); //存储每对数的区间结果

	for (int i = 1; !colors.empty(); i++) {  //i从1开始,结束条件是colors为空时说明找完了

		sort(colors.begin(), colors.end(), [&](const int a, const int b) {
			return x[a][i] < x[b][i];
		});//每次循环都是从第i个下标排序

		for (int j = 0; j < min(r, int(colors.size())); j++) {//求每一对结果
			intervals[colors[j]] = make_pair(x[colors[j]][i - 1], x[colors[j]][i]);
		}
		colors.erase(colors.begin(), colors.begin() + min(r, int(colors.size())));//删除本次循环找过的不超过r个元素
	}

	for (int i = 1; i <= n; i++)
		cout << intervals[i].first << " " << intervals[i].second << endl;
}

int main() {

	solve();

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值