2部マッチングの個数にしかみえなくて絶望。
経過した秒数 D の数はたかが知れている。
D を決め打ちしたとすれば、2部グラフが作れる。
+D 秒後と -D 秒後の 2 つしかマッチさせる候補がないので
あるマッチングの連結成分の右側と左側の頂点の個数は
R == L
R + 1 == L
R == L + 1
の3パターンしかない。
R == L のマッチングの個数は 1 通り
R + 1 == L はどこの入次数を 2 にするかで L 通り
R == L + 1 は成り立たない。
後は、連結成分ごとのパターン数の積を計算する。
class OneDimensionalBalls {
public:
long long countValidGuesses(vector <int> F, vector <int> S)
{
vector<int> diff;
for (int i = 0; i < F.size(); ++i) {
for (int j = 0; j < S.size(); ++j) {
diff.push_back(abs(F[i] - S[j]));
}
}
sort(diff.begin(), diff.end());
diff.erase(unique(diff.begin(), diff.end()), diff.end());
diff.erase(remove(diff.begin(), diff.end(), 0), diff.end());
sort(F.begin(), F.end());
sort(S.begin(), S.end());
lli ret = 0;
for (int d = 0; d < diff.size(); ++d) {
cout << diff[d] << endl;
vector<lli> v;
set<int> vis_F;
set<int> vis_S;
for (int i = 0; i < F.size(); ++i) {
if (vis_F.count(F[i])) continue;
int prev_F = vis_F.size();
int prev_S = vis_S.size();
vis_F.insert(F[i]);
queue<int> q;
for (q.push(F[i]); q.size(); q.pop()) {
int n = q.front();
int e[] = {n - diff[d], n + diff[d]};
int f[] = {n - 2 * diff[d], n + 2 * diff[d]};
for (int j = 0; j < 2; ++j) {
if (binary_search(S.begin(), S.end(), e[j])) {
vis_S.insert(e[j]);
if (binary_search(F.begin(), F.end(), f[j]) && !vis_F.count(f[j])) {
q.push(f[j]);
vis_F.insert(f[j]);
}
}
}
}
int diff_F = vis_F.size() - prev_F;
int diff_S = vis_S.size() - prev_S;
if (diff_F == diff_S) v.push_back(1);
if (diff_F + 1 == diff_S) v.push_back(diff_S);
if (diff_F == diff_S + 1) v.push_back(0);
}
ret += accumulate(v.begin(), v.end(), 1, multiplies<int>());
}
return ret;
}
};