题意:给一个长度为n的序列,要求将其中一些数字用小于m的数字替换使得这个序列中不出现重复的数字,并且奇数和偶数的个数一样。
思路:
首先将重复的数字进行转换,看看原序列是那种数多,假如奇数多,让重复的奇数转换成偶数,让重复的偶数转换成没出现过的偶数,用两个变量表示现在可以选的奇数和偶数是那些,不要超过m。接下来序列没有重复的数字,然后扫一遍,奇数多,就找奇数转成偶数,否则找偶数。
ac代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<vector>
#include<unordered_map>
#define mod (1000000007)
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;
unordered_map<ll,int> mp;
ll a[maxn];
int main() {ll n,m,ne=0,no=0,cg=0,ff=1,num=0;scanf("%lld%lld",&n,&m);for(int i=1;i<=n;i++) scanf("%lld",&a[i]),mp[a[i]]++,no+=a[i]&1,ne+=(1-a[i]&1);ll even=2,odd=1,nno,nne;cg=ne-no;for(auto it:mp){if(it.second>1){if(it.first&1) nne+=it.second-1;else nno+=it.second-1;}}for(int i=1;i<=n;i++){while(mp[even]) even+=2;while(mp[odd]) odd+=2;if(mp[a[i]]>1){num++;mp[a[i]]--;if (a[i] & 1)if (cg < 0) {//奇数多,奇数->偶数a[i] = even;if(even>m)ff=0;mp[even]++;cg+=2;} else {//奇数->奇数a[i] = odd;if(odd>m)ff=0;mp[odd]++;}else if (cg <= 0) {//奇数多,偶数->偶数a[i] = even;if(even>m)ff=0;mp[even]++;} else {//偶数->奇数a[i] = odd;if(odd>m)ff=0;mp[odd]++;cg-=2;}}}if(!ff||n&1) puts("-1");else{for(int i=1;i<=n;i++){while(mp[even]) even+=2;while(mp[odd]) odd+=2;if(a[i]&1&&cg<0){num++;a[i]=even;if(even>m)ff=0;mp[even]++;cg+=2;}else if(a[i]%2==0&&cg>0){num++;a[i]=odd;if(odd>m)ff=0;mp[odd]++;cg-=2;}}if(ff==0) puts("-1");else{printf("%d\n",num);for(int i=1;i<=n;i++) printf("%lld%c",a[i],i==n?'\n':' ');}//特殊判断没有相同的时候}return 0 ;
}