http://agc016.contest.atcoder.jp/tasks/agc016_b
最初1CaseだけWAだったからこれはいけると思ったけどそうでもなかった。
A[i]の最大値と最小値(それぞれrv,lvとする)の差が1か0で場合分けする
1. 0のとき
rv = N - 1なら全色違うものを置けばOK
rv * 2 <= Nなら同じ色のペアを作っていって、N - rv * 2個分は使った色を適当にアサインすればよい。
2. 1のとき
lvの個数をcmin,rvの個数をcmaxと置く。
観察するとA[i] = lv, A[j] = lv, i != jを満たす任意のi、jについて違う色をアサインしなくてはならなくて、
A[i] = rvを満たす任意のiに関してはA[j] = rv, i != jを満たすjが存在する必要がある。
cmin >= rvだと、A[i] = lvを満たすiの集合にrv以上種類の色をアサインしてしまう。よって不可。
また2 * (rv - cnt) > cmaxだと、対応するjが存在しないiが現れてしまう。よって不可。
なのでcmin + 1 <= rv && 2 * (rv - cnt) <= cmaxが必要条件。十分性は証明簡単。
int N; int A[MAX_N]; void solve() { cin >> N; int lv = inf, rv = -1; rep(i, 0, N) { cin >> A[i]; MIN(lv, A[i]); MAX(rv, A[i]); } if(rv - lv > 1) { cout << "No\n"; } else { if(rv - lv == 0) { if(rv == N - 1) cout << "Yes\n"; else if(rv * 2 <= N) cout << "Yes\n"; else cout << "No\n"; } else { int cnt = 0; rep(i, 0, N) { if(A[i] == lv) cnt++; } if(cnt + 1 <= rv && 2 * (rv - cnt) <= N - cnt) cout << "Yes\n"; else cout << "No\n"; } } }
2の場合分けをミスった。