1 条题解
-
0
自动搬运
来自洛谷,原作者为

Coffee_zzz
沉覆z搬运于
2025-08-24 22:54:02,当前版本为作者最后更新于2023-12-07 23:10:12,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
我们首先分析一下题目给出的操作。
对于某个元素 ,如果序列 中存在另一个元素 满足 ,那么显然,去掉 后的序列 的 和原本的序列 的 相等,所以操作后, 会变成原本的序列 的 。
同时,对于某个元素 ,若其满足 大于原本的序列 的 ,那么显然,是否去掉 对序列 的 没有影响,所以操作后, 也会变成原本的序列 的 。
我们再来考虑,对于某个元素 ,若其满足:
- 序列 中不存在另一个元素 满足 ;
- 小于原本序列 的 ;
那么,去掉 之后,序列 的 就会变成 ,所以操作前后, 的值不变。
于是我们明白了操作前后序列 的变化。可以用桶维护,做到以 的复杂度进行一次操作,那么对于 的情况,我们直接模拟即可。
我们继续分析。
我们先进行第一次操作,把所有满足序列 中存在另一个元素与其相等或其大于序列 的 的元素的值都修改为序列 的 。
然后我们再进行第二次操作,内容和第一次操作相同。
于是容易证明,此时的序列 除最大值外,剩余的元素都满足不存在另一个元素 与其相等,而且最大值要么等于序列 的 的值加一,要么等于序列 的 的值减一。
我们设序列 中的最大值为 。根据我们之前分析的内容,若序列 中只有一个元素的值为 ,则 的值不会再改变;若序列 中有多个元素的值为 ,我们分两类讨论:
- 若 等于序列 的 ,则所有值等于 的元素的值都会变为 ,此时新的序列 的 为 ;
- 若 等于序列 的 ,则所有值等于 的元素的值都会变为 ,此时新的序列 的 为 。
可以发现,若序列 中有多个元素的值为 ,则进行多次操作时, 的值在一直循环,不断加一、减一,每两次操作的效果可以抵消,于是可以得到:
- 当 为偶数时,进行 次操作后的序列 与进行 次操作后的序列 相同;
- 当 为奇数且 时,进行 次操作后的序列 与进行 次操作后的序列 相同。
那我们直接根据此模拟即可。
#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; }
- 1
信息
- ID
- 9489
- 时间
- 500ms
- 内存
- 512MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者