CodeForces

/*
  此题略坑的是,最终输出的那个数列,不能有重复的数字,这个坑点之前一直没发现,结果一直WA,其实题目也没明说这一点,但是对某组数据的解释中,有一句“只有一种答案”,可以从这句中猜测出来
  
  借鉴自代码:
  http://blog.csdn.net/senyelicone/article/details/72909698
  不过我略作了修改,省去了一次循环...即博客代码中的
  
  for(int i=1;i<=n;i++) if(a[i]==b[i]) c[i]=a[i],k[c[i]]=1;  
        else now=i;
以及
for(int i=1;i<=n;i++)  
          if(a[i]==b[i]) c[i]=a[i],k[c[i]]=1;  
          else d[tot--]=i;  

---0824更新---
后来发现我错怪cf了,是我自己英语不好,导致专有术语认不出来的锅
combination和permutation分别是组合和排列的英文单词,按照数学中的排列组合的定义,一组排列中的所有数字,本就是不能有重复的...
看来除了好好练编程,还得好好学英语
  
*/



#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int a[N], b[N], c[N], v[N];
int d[5];
//a、b为输入的两个数列,c为最终的输出数列,v用来记录,c数组的各位置的值是否已经确定(因为c中所有数字,最多只能用一次,注意permutation是排列,以及排列的定义)
//d[i]中的值,用来记录不相等的第i对数字的下标 
int main()
{
//	cin.tie(0);
//  cin.sync_with_stdio(false);
  	
	int n;
	while (cin >> n)
	{
		memset(v, 0, sizeof(v));
		int tot = 0, kase = 1, temp;
		for (int i = 1; i <= n; i++) cin >> a[i];
		for (int i = 1; i <= n; i++) cin >> b[i];
		
		for (int i = 1; i <= n; i++)
		{
			if (a[i] == b[i])
			c[i] = a[i], v[a[i]] = 1; //相等的直接作为c[i]的值,v数组 v[i] = 1的意义是,数字i在c数组中已经出现过了
			else
			tot++, d[kase++] = i;//tot记录失配隔宿,d数组 d[i] = b表示第i次失配是在a[b]的位置
		}
		if (tot == 1)
		{
			for (int i = 1; i <= n; i++)
			if (!v[i]) temp = i;
			c[d[1]] = temp;
		}
		else
		{
			if ( a[d[1]] == b[d[2]] || v[a[d[1]]] || v[b[d[2]]] ) //2个失配位置的情况,如果对某个失配位置,如果数组a在该位置的值,已经在c数组中出现过了,则数组c的该位置。应填入数组b在该失配位置的值
			//如果失配位置标号1和2,且a1 == b2,则c数组中的对应位置应选取a2和b1,这样才能保证两个数列都恰好1个位置和c数列不同
			c[d[1]] = b[d[1]], c[d[2]] = a[d[2]];
			else
			c[d[1]] = a[d[1]], c[d[2]] = b[d[2]];
		}
		cout << c[1];
		for(int i = 2; i <= n; i++)
		cout << " " << c[i];
		cout << endl;
		
	} 
	return 0;
}


/*cf上的代码


它的思路更为特别,因为题目要求输出的数组不能有重复元素,也即1~n出现且仅出现一次,但是,数组a中又有(n-1)个元素和输出的数组的元素一样,所以,1~n中一定有一个数据没出现,数组a中的(n-1)种元素,一定有一个元素出现了两次,把出现了两次的元素找出来,先把该元素第一次出现的位置,赋值为没出现过的那个元素,若a换完后,和b刚好一个元素不同,则更换成功,否则将x赋值回第一次出现的位置,对第二次出现的位置,再赋值...该代码中,两个位置是用循环找的,但我觉得,可以在找x时,就把x出现的2个位置记录下来...用一个pair,辅助变量kase记录下2次分别是在什么位置出现,少掉一次循环

此外,找x和找y比较特殊,因为找x时,还要找到x对应的两个下标,所以,i从1到n的循环,枚举的是fre[a[i]];而找y时,如果继续这样枚举,是找不到的,因为,既然fre[a[i]]都等于0了,说明,我想要找的那个频次为0的数,在数组a中根本没出现,如果还那样找,就根本找不到...所以找y时,是换成了i从1到n循环,枚举fre[i]本身,这点尤其注意!!!因为一开始,我也没有想得很透彻清楚,我最初写的时候,就出现了找y找不到的局面

以及,后来WA了一次,仔细检查发现,fre每次循环都有memset清零,我忘记写了...这个错误经常犯,尤其多组数据时,很多次WA都是因为没有清空上组的数据,慎之!

参考了cf上的一段代码,因为不是blog贴不了网址,不过源代码就是下面这样:
(下次来填一个坑,怎么在cf上查看后台数据以及别人的正确代码)

#include <bits/stdc++.h>
using namespace std;
int a[1002],b[1002],fr[1002];
int main()
{
		int n,x,y;
		cin>>n;
		for(int i=0;i<n;i++)
		{
			cin>>a[i];
			fr[a[i]]++;
		}
		for(int i=0;i<n;i++)
			cin>>b[i];
		for(int i=1;i<=n;i++)
		{
			if(fr[i]==2)
				x=i;
			if(fr[i]==0)
				y=i;
		}
		for(int i=0;i<n;i++)
		{
			if(a[i]==x)
			{
				a[i]=y;
				int ct=0;
				for(int j=0;j<n;j++)
					if(a[j]!=b[j])
						ct++;
				if(ct==1)
				{
					for(int k=0;k<n;k++)
						cout<<a[k]<<" ";
					return 0;
				}
				a[i]=x;
			}
		}
	return 0;
}
*/


#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int a[N], b[N],fre[N]; // fre is short for frequency
pair<int, int> same; //记录a中出现过2次的数,分别是在哪两个位置出现
void printa(int n)
{
	cout << a[1];
	for (int i = 2; i <= n; i++)
	cout << " " << a[i];
	cout << endl; 
}
int main()
{
	int n;
	while (cin >> n)
	{
		memset(fre, 0, sizeof(fre));
		int kase = 0, x, y; //x是出现两次的数,y是没出现的数,kase是标记当前找的是x的第几次出现
		for (int i = 1; i <= n; i++) cin >> a[i], fre[a[i]]++;
		for (int i = 1; i <= n; i++) cin >> b[i];
		
		for (int i = 1; i <= n; i++)
		{
			if (fre[a[i]] == 2) //出现两次的数,究竟是在a的哪个下标出现了两次,分别记录下来 
			{
				 x = a[i];
				 if (!kase) kase++, same.first = i;
				 else kase++, same.second = i;
			}
			if (fre[i] == 0) y = i;
		}
	//	cout << "x = " << x << " y = " << y << " first = " << same.first << " second = " << same.second << endl;
		
		a[same.first] = y; int cnt = 0;
		for (int i = 1; i <= n; i++)
		{
			if (a[i] != b[i]) cnt++;
		}
		if (cnt == 1)
		{
			printa(n);
			continue;
		}
	//	cout << "test: " << x << " " << y << endl;
		
		a[same.first] = x, a[same.second] = y;
		printa(n);
	}
	return 0;
}


原文地址:https://www.cnblogs.com/mofushaohua/p/7789510.html