題意:給一個長度爲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 ;
}