CF1552E Colors and Intervals 做题记录

n×kn \times k 个格子,编号从 11n×kn \times k,染成 nn 种颜色,每种颜色恰好 kk 个。
构造 nn 个区间,第 ii 个区间 [ai,bi][a_i, b_i] 满足

  • 1ai<bin×k1 \le a_i < b_i \le n \times k
  • aia_i 个和第 bib_i 个格子的颜色都是 ii
  • 每个格子被包含不超过 nk1\lceil \frac{n}{k-1} \rceil 次。

1n1001\le n\le 1002k1002\le k\le 100

先求出 posi,jpos_{i,j} 表示颜色 iijj 次出现的位置。

不难发现,只要把 nn 个颜色分为 k1k-1 组,每组大小 nk1\le \lceil\frac{n}{k-1}\rceil,不同组的区间互不相交即可。并且每个颜色选择区间 [posi,j,posi,j+1][pos_{i,j},pos_{i,j+1}] 肯定是最优的。

考虑较为简单的情况的构造,k=2k=2 未免太简单了,考虑 k=3k=3 的情况。这时要分 22 组,每组大小 n2\lceil\frac{n}{2}\rceil,稍加思考可以发现,只要按照 posi,2pos_{i,2} 排序,前 n2\lceil\frac{n}{2}\rceil 个颜色选择区间 [posi,1,posi,2][pos_{i,1},pos_{i,2}],其它颜色选择区间 [posi,2,posi,3][pos_{i,2},pos_{i,3}] 即可。

考虑推广这个构造方法,容易发现,只要重复 k1k-1 次,第 TT 次按照 posi,T+1pos_{i,T+1} 排序,排序后前 nk1\lceil\frac{n}{k-1}\rceil 个颜色选择区间 [posi,T,posi,T+1][pos_{i,T},pos_{i,T+1}] 即可。

代码如下:

#include <iostream>
#include <algorithm>
#include <cstdio>

using namespace std;

const int S=105;

int n,k;
int pos[S][S],tot[S];
int ansl[S],ansr[S];
int id[S];

int main()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n*k;i++)
	{
		int x;
		scanf("%d",&x);
		pos[x][++tot[x]]=i;
	}
	int val=n/(k-1)+!!(n%(k-1));
	for(int i=1;i<=k-1;i++)
	{
		int cnt=0;
		for(int j=1;j<=n;j++) if(ansl[j]==ansr[j]) id[++cnt]=j;
		sort(id+1,id+cnt+1,[&](int x,int y){return pos[x][i+1]<pos[y][i+1];});
		for(int j=1;j<=cnt&&j<=val;j++) ansl[id[j]]=pos[id[j]][i],ansr[id[j]]=pos[id[j]][i+1];
	}
	for(int i=1;i<=n;i++) printf("%d %d\n",ansl[i],ansr[i]);
	return 0;
}