Codeforces 746E Numbers Exchange 模拟

来源:互联网 发布:java 反射 实例化单例 编辑:程序博客网 时间:2024/06/06 09:33

点击打开链接

题意:n个数a[i],m个数1~m 问最少要多少次交换,使得数组a中odd个数等于even个数 && 所有数都不同,无解输出-1  
记录odd个数,先去掉重复的元素 ans>=该步交换次数
odd>n/2 找到m中下一个能交换的偶数   
odd==n/2 则交换相同奇偶性即可
odd<n/2 找到m中下一个能交换的奇数
此时,a中无重复元素  若odd<n/2 则用只能用偶数换下一个能取的奇数 odd>n/2也一样 ,最后判断odd是否等于n/2即可 ans>=该步交换次数 则ans肯定为最小

#include <bits/stdc++.h>using namespace std;const int N=2e5+20;int n,m,a[N],o,e,ans;bool flag;map<int,int> mp;void swap_even(int i){while(e<=m&&mp[e])e+=2;if(e>m)flag=false;elsemp[e]++,mp[a[i]]--,a[i]=e;}void swap_odd(int i){while(o<=m&&mp[o])o+=2;if(o>m)flag=false;elsemp[o]++,mp[a[i]]--,a[i]=o;}int main(){while(cin>>n>>m){mp.clear();int odd=0,even=0;ans=0;flag=true;for(int i=1;i<=n;i++){scanf("%d",&a[i]);mp[a[i]]++;if(a[i]%2)odd++;}//先换重复的o=1,e=2; // for(int i=1;i<=n;i++) { if(mp[a[i]]==1) continue; //cout<<i<<' '<<a[i]<<' '<<mp[a[i]]<<endl; ans++; if(odd>n/2) { if(a[i]%2) odd--; swap_even(i);}else if(odd==n/2){if(a[i]%2)swap_odd(i);elseswap_even(i);}else{if((a[i]%2)==0)odd++;swap_odd(i);}}for(int i=1;i<=n;i++){if(odd>n/2&&a[i]%2)swap_even(i),odd--,ans++;if(odd<n/2&&(a[i]%2)==0)swap_odd(i),odd++,ans++;if(odd==n/2)break;}if(flag==false||odd!=n/2){puts("-1");continue;}cout<<ans<<endl;for(int i=1;i<=n;i++)cout<<a[i]<<' ';cout<<endl;}return 0;}


0 0