"蔚来杯"2022牛客暑期多校训练营7 C-Constructive Problems Never Die
问题描述
Grammy has a sequence A of length n.
Please find a permutation P such that Pi≠Ai for all i.
输入格式
There are multiple test cases.
The first line contains a single integer T (1≤T≤100000), denoting the number
of test cases.
For each test case:
The first line contains a single integer n (1≤n≤100000).
The second line contains n integers A1,A2,…,An (1≤Ai≤n).
It is guaranteed that the sum of n does not exceed 500000.
输出格式
For each test case:
If the permutation does not exist, output “NO” in one line.
Otherwise output “YES” in the first line, then output n integers in the second line,
denoting the permutation P1,P2,…,Pn.
样例输入
3
3
3 3 3
3
3 2 1
6
1 1 4 5 1 4
样例输出
NO
YES
1 3 2
YES
4 5 1 2 3 6
题解
给定一个序列a,求一个全排列p,满足p[i]!=a[i]
若a中每个数都相等,则无论怎样的排列一定会存在一个p[i]==a[i]
只要序列a中存在一个不同的数,就一定存在满足条件的全排列
先假设一个初始全排列b[i]=i,对于b中某个不满足条件的位置j(即a[j]==b[j]),由于b[j]和b[j+1]不相等,若a[j]==b[j],则a[j]和b[j+1]一定不等,交换b[j]和b[j+1],就能使b[j]满足条件;若b中最后一个数不满足条件,此时无法通过和下一个交换使其满足条件,我们可以从前面满足条件的位置中找一个和b[n]交换仍然满足条件的位置进行交换
1 #include <cstring> 2 #include <cstdio> 3 int T,n,a[100005],b[100005]; 4 int cnt[100005],p[100005],t; 5 int main() 6 { 7 int i,j; 8 scanf("%d",&T); 9 while (T--) 10 { 11 memset(cnt,0,sizeof(cnt)); 12 t=0; 13 scanf("%d",&n); 14 for (i=1;i<=n;i++) 15 scanf("%d",&a[i]), 16 b[i]=i,cnt[a[i]]++; 17 for (i=1;i<=n;i++) 18 { 19 if (cnt[i]==n) break; 20 if (b[i]!=a[i]) 21 { 22 p[++t]=i; 23 continue; 24 } 25 if (i!=n) 26 { 27 b[i]^=b[i+1]; 28 b[i+1]^=b[i]; 29 b[i]^=b[i+1]; 30 p[++t]=i; 31 continue; 32 } 33 for (j=1;j<=t;j++) 34 if (b[p[j]]!=a[n] && b[n]!=a[p[j]]) 35 { 36 b[p[j]]^=b[n]; 37 b[n]^=b[p[j]]; 38 b[p[j]]^=b[n]; 39 break; 40 } 41 } 42 if (i==n+1) 43 { 44 printf("YES\n"); 45 for (j=1;j<n;j++) 46 printf("%d ",b[j]); 47 printf("%d\n",b[n]); 48 } 49 else printf("NO\n"); 50 } 51 return 0; 52 }