CodeForces

来源:互联网 发布:事情正在起变化 知乎 编辑:程序博客网 时间:2024/05/17 07:41
/*  此题略坑的是,最终输出的那个数列,不能有重复的数字,这个坑点之前一直没发现,结果一直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数组中已经出现过了elsetot++, 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]];elsec[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 frequencypair<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;}


原创粉丝点击