けんちょんの競プロ精進記録

競プロの精進記録や小ネタを書いていきます

AtCoder ABC 278 C - FF (4Q, 灰色, 300 点)

SNS を題材にした set の練習問題

問題概要

 N 人から SNS について、次の  Q 個のクエリに答えよ(初期状態では全員が誰もフォローしていない)。

  • クエリタイプ 1:人  A が人  B をフォローする(フォロー済みの場合は何もしない)
  • クエリタイプ 2:人  A が人  B のフォローを解除する(フォローしてない場合は何もしない)
  • クエリタイプ 3:人  A, B が相互にフォローし合っているかどうかを判定する

制約

  •  2 \le N \le 10^{9}
  •  1 \le Q \le 2 \times 10^{5}

考えたこと

 A が人  B をフォローしている状態をペア値 {A, B} で表すことにしよう。そうして、フォロー関係すべてを表す集合 S を次のように定義しよう。


S:フォロー関係 {A, B} を格納した集合


C++ であれば、具体的には set<pair<int, int>> 型で実現できる。そうすると次のように実装できる。

  •  A が人  B をフォローする:S.insert({A, B})
  •  A が人  B のフォローを解除する:S.erase({A, B})
  •  A, B が相互フォローであるかを確認する:S.count({A, B}) && S.count({B, A}) が true かどうかで判定

計算量は  O(Q \log Q) となる。

コード

#include <bits/stdc++.h>
using namespace std;

int main() {
    int N, Q, T, A, B;
    cin >> N >> Q;

    set<pair<int,int>> S;
    while (Q--) {
        cin >> T >> A >> B;
        if (T == 1) S.insert({A, B});
        else if (T == 2) S.erase({A, B});
        else {
            if (S.count({A, B}) && S.count({B, A})) cout << "Yes" << endl;
            else cout << "No" << endl;
        }
    }
}