Official

F - 集合の問題 / A Set Problem Editorial by physics0523


\(S\)\(T\) の和集合を毎回求めていては実行時間制限に間に合いません。 (要素数の合計が最悪ケースで \(10^{10}\) 以上に達するからです)

そこで、 ( \(S\)\(T\) の和集合の大きさ ) = ( \(S\) の大きさ ) \(+\) ( \(T\) の大きさ ) \(-\) ( \(S\)\(T\) の共通部分の大きさ ) という性質を利用します。

変形した後の前2項は直ちに求まります。
( \(S\)\(T\) の共通部分の大きさ ) については、 \(T\) の各要素について \(S\) 中に含まれるか判定して数えていけばよく、これは集合を管理するデータ構造 ( 例えば C++ では set ) を用いると \(T\) の1要素あたり \(O(\log S)\) の時間計算量で実現できます。

\(T\) の大きさの総和がそう大きくならないという制約から、この解法は実行時間制限に間に合うことも分かります。

実装例 (C++):

#include<bits/stdc++.h>

using namespace std;

int main(){
  int n;
  cin >> n;
  set<int> s;
  for(int i=0;i<n;i++){
    int x;
    cin >> x;
    s.insert(x);
  }
  int q;
  cin >> q;
  while(q>0){
    q--;
    int m;
    cin >> m;
    int res=n+m;
    for(int i=0;i<m;i++){
      int x;
      cin >> x;
      if(s.find(x)!=s.end()){res--;}
    }
    cout << res << "\n";
  }
}

posted:
last update: