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,⋯,an−1,an,an变为新的最小非负整数。所以每次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;
}
分类:
算法刷题
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】