D. Secret Santa
思路:把输入数组中重复的数用没有被输入的数替换下来,形成全排列,我们只需要存下来那些没有输入的数
替换思路:从小到大存这些数,然后从大到小使用,这样就能尽量使得和替换位置的下标不相等
#include <bits/stdc++.h>
using namespace std;
const int maxn=300000+50;
int n,m,ans,T;
int vis[maxn],a[maxn];
int cnt,h[maxn];
int main()
{
scanf("%d",&T);
for (int oo = 1; oo <= T; ++oo)
{
scanf("%d",&n);
cnt = 0; ans = n;
for (int i=1; i<=n; ++i)
scanf("%d",&a[i]),vis[a[i]]++;
for (int i=1; i<=n; ++i)
if (!vis[i]) h[++cnt]=i,--ans;
for (int i = 1; i <= n; ++i)
if (vis[a[i]] > 1 && h[cnt] != i)
{
vis[a[i]]--;
a[i] = h[cnt--];
}
printf("%d\n",ans);
for (int i = 1; i <= n; ++i)
printf("%d ",a[i]), vis[i]=0;// 顺便初始化
printf("\n");
}
return 0;
}
本文介绍了一种解决SecretSanta问题的方法,通过将重复数值替换成未出现过的数值来构造全排列,确保每个数值与对应下标不同。算法首先统计未出现的数值,并按特定顺序进行替换,最后输出替换后的序列。

被折叠的 条评论
为什么被折叠?



