codeforces刷题(1100):1863C_div1+div2

C、MEX Repetition

跳转原题点击此:该题地址

1、题目大意

  给定一个数组,要求每次依次从左到右ai替换为当前数组的最小非负整数(每次替换一个数后,最小非负整数也会发生改变)。问你,经过k次的操作后,最终数组是什么。
  注意:该数组的数 和 最小非负整数,是从0,1,,n这一共n+1个数中选出,每个数必须出现一次。

2、题目解析

  我们发现,每次更换数组时,a1会被最小非负整数替换,而a2则会被a1原来的书替换,以此类推,而an原本的数则会称为新的最小非负整数。
  所以,令最小非负整数为x,则其与原数组生成新的数组:a1,a2,,an,x
  第一次MEX新数组变为x,a1,a2,,an1,anan变为新的最小非负整数。所以每次MEX都会将新数组往后移动一格,最后一个到第一个来。
  同时我们注意到,每n+1次MEX后,数组将会重新变为输入时的数组,所以我们可以对其取余,减少重复操作。

3、具体代码

#include<bits/stdc++.h>

using namespace std;

int T;
int n, k;

// 定义第一个最小的非负整数为x,原输入为a1,a2,...,an
// 原理在于:每次都是x覆盖第一个数,然后后面的数依次用前一个被替代的数覆盖
// 所以发现:a1,a2,...,an,x,第一次为x,a1,a2,...a(n-1),an,每次MEX都将数组往后移动一格
void solve()
{
	cin >> n >> k;
	vector<int>f(n + 1);
	set<int>se;
	for(int i = 0; i < n; i++)
	{
		cin >> f[i];
		se.insert(f[i]);
	}
	for(int i = 0; i <= n; i++)
	{
		if(!se.count(i))
		{
			f[n] = i;
			break;
		}
	}
	k %= (n + 1);	// 因为当k次数为n+1的倍数则与输入无异
	if(k == 0)	
		k = n + 1;
	int cnt = n, idx = n - k + 1;	// idx为k次MEX后的第一个头下标
	while(cnt--)
	{
		// 注意顺序:先输出头下标,如何下标++,如果超过范围则返回第一个
		cout << f[idx] << " ";
		idx++ ;
		if(idx == n + 1)
			idx = 0;
	}
	cout << endl;
	
}

int main()
{
	cin >> T;
	while (T--)
	{
		solve();
	}

	return 0;
}

 

posted @   Tom-catlll  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
// 数学公式
点击右上角即可分享
微信分享提示