P10032 题解(2023 激励计划评分 8)
Coffee_zzz · · 题解
我们首先分析一下题目给出的操作。
对于某个元素
同时,对于某个元素
我们再来考虑,对于某个元素
- 序列
a 中不存在另一个元素a_p 满足a_k=a_p ; -
那么,去掉
于是我们明白了操作前后序列
我们继续分析。
我们先进行第一次操作,把所有满足序列
然后我们再进行第二次操作,内容和第一次操作相同。
于是容易证明,此时的序列
我们设序列
- 若
x+1 等于序列a 的\operatorname{mex} ,则所有值等于x 的元素的值都会变为x+1 ,此时新的序列a 的\operatorname{mex} 为x ; - 若
x-1 等于序列a 的\operatorname{mex} ,则所有值等于x 的元素的值都会变为x-1 ,此时新的序列a 的\operatorname{mex} 为x 。
可以发现,若序列
- 当
m 为偶数时,进行m 次操作后的序列a 与进行2 次操作后的序列a 相同; - 当
m 为奇数且m\ne 1 时,进行m 次操作后的序列a 与进行3 次操作后的序列a 相同。
那我们直接根据此模拟即可。
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,a[N],cnt[N];
void work(){
int res=0;
for(int i=0;i<=n;i++) cnt[i]=0;
for(int i=1;i<=n;i++) if(a[i]<=n) cnt[a[i]]++;
for(int i=n;i>=0;i--) if(cnt[i]==0) res=i;
for(int i=1;i<=n;i++) if(a[i]>res||cnt[a[i]]>1) a[i]=res;
}
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
work();
if(m!=1){
work();
if(m%2==1) work();
}
for(int i=1;i<=n;i++) cout<<a[i]<<(i==n?'\n':' ');
}
signed main(){
ios::sync_with_stdio(0);
int T=1;
cin>>T;
while(T--) solve();
return 0;
}