バイトの競プロメモ

主に競技プログラミング

D - Pair Cards

https://atcoder.jp/contests/cf16-final-open/tasks/codefestival_2016_final_d

 

解法

modを取って対応する二つの集合のマッチングを考える

ここで、仮に元の数が同じもの達のペアを作った時、使われなかったものを優先的にマッチングに使う(ここで全て使い切る)

残った自分たち同士で繋いだものが答え

 

 

https://atcoder.jp/contests/cf16-final-open/submissions/4682601

void solve() {
cin >> n >> m;
na(a, n);
umapi mv;
rep(i, n) {
mv[a[i]]++;
}
vvp(d, k5);
rep(i, k5)d[i] += mp(0, 0);
fora(v, mv) {
int mo = mod(v.fi, m);
int c = v.se;
d[mo][0].se += c % 2;
d[mo] += mp(1, c / 2 * 2);
}

rep(l, k5) {
int r = mod(-l, m);
if (l > r)brk;
if (l == r) {
int sum = 0;
fora(v, d[l])sum += v.se;
cou += sum / 2;
} else {
int &nl = d[l][0].se;
int &nr = d[r][0].se;
if (nl <= nr) {
cou += nl;
nr -= nl;
nl = 0;
//lからnr分削る
fora(v, d[l]) {
int de = min(v.se, nr);
v.se -= de;
nr -= de;
cou += de;
}
fora(v, d[l]) {
if(v.fi)cou += v.se / 2;
}
fora(v, d[r]) {
if(v.fi)cou += v.se / 2;
}
} else {
cou += nr;
nl -= nr;
nr = 0;
//rからnl分削る
fora(v, d[r]) {
int de = min(v.se, nl);
v.se -= de;
nl -= de;
cou += de;
}
fora(v, d[l]) {
if(v.fi)cou += v.se / 2;
}
fora(v, d[r]) {
if(v.fi)cou += v.se / 2;
}
}
}
}
cout << cou << endl;

}