CF1381C Solution
题解
对于需要颜色相同且位置不同的元素,易得同种颜色数量的最大值越小,越容易构造成功。因此对于颜色、位置均需相同的元素,利用优先队列使其选择数量最大的元素填充。求出剩余元素中同种颜色数量的最大值\(ma\),将剩余元素按照值从小到大存储。因为\(i\)和\(i+ma\)元素值一定不等,所以两者可以互换位置,具体双指针维护即可,详见代码。剩余的位置需要填充原序列中没有的颜色,因为有\(n+1\)种颜色,一定存在可选颜色。
AC代码
#include<bits/stdc++.h>
#define pb push_back
#define pii pair<int,int>
#define mp make_pair
#define se second
using namespace std;
const int N=1e5+10;
int b[N],ans[N];
vector<int> num[N];
vector<pii > res;
priority_queue<pii > q;
int main()
{
int t,n,x,y;
scanf("%d",&t);
while(t--)
{
memset(ans,0,sizeof(ans)); res.clear();
while(!q.empty()) q.pop();
scanf("%d%d%d",&n,&x,&y);
for(int i=1;i<=n+1;i++) num[i].clear();
for(int i=1;i<=n;i++) {scanf("%d",&b[i]); num[b[i]].pb(i);}
int ava,tmp=x,ma=0,cnt=0;
for(int i=1;i<=n+1;i++)
{
if(num[i].empty()) ava=i;
else q.push(mp(num[i].size(),i));
}
while(tmp--)
{
pii z=q.top(); q.pop();
ans[num[z.se].back()]=z.se; num[z.se].pop_back();
if(!num[z.se].empty()) q.push(mp(num[z.se].size(),z.se));
}
for(int i=1;i<=n+1;i++)
{
tmp=num[i].size(),ma=max(ma,tmp);
for(int j=0;j<tmp;j++) res.pb(mp(i,num[i][j]));
}
if(n-y<ma*2-n+x) {printf("NO\n"); continue;}
tmp=res.size();
for(int i=0;i<tmp;i++)
{
if(cnt>=y-x) break;
ma%=res.size();
if(res[i].first!=res[ma].first) ans[res[i].se]=res[ma++].first,cnt++;
}
printf("YES\n");
for(int i=1;i<=n;i++) printf("%d ",ans[i]?ans[i]:ava);
printf("\n");
}
return 0;
}