A - カードゲーム 2 (Card Game 2) Editorial by blueberry1001


満点解法のみを解説します。 行いたい操作は以下です。

  • \(A\)に含まれる数 \(x\)であって、\(x+3\)\(x+6\) のどちらもが \(A\)に含まれるような \(x\)が存在するか判定する。

\(x\)の候補は\(A\)に含まれる数です。これは、for文などで\(A\)に含まれる要素を全て試せばよいです。

さて、ここで「\(x+3\)\(x+6\) のどちらもが \(A\)に含まれる」という条件を判定したいです。ですが、存在判定をcount関数などの愚直で低速な方法で行うとTLEしてしまいます。

ここでset(集合型)というデータ構造を使うことを考えます。setを使うことで、

  • 集合に要素を追加する。
  • 集合に要素が存在するか判定する。
  • 集合から要素を削除する

というような操作を、集合の要素数を\(N\)として計算量 \(O( \log_{}N)\) で行うことができます。setを使うことで行いたい操作を高速に行うことができ、ACすることができます。計算量は\(O(N \log N)\) となります。

コードは以下のようになります。(C++コードも下に記載しています。)

Pythonによる実装

N = int(input())
A = list(map(int,input().split()))

#Aの要素からなる集合型を宣言する。
s = set(A)

#答えが見つかったらansをTrueにする。
#最初はFalseにしておく。
ans = False

for x in A:
  if x+3 in s and x+6 in s:
    ans = True

if ans:
  print("Yes")
else:
  print("No")

提出コード(Python)

C++による実装

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

int main(){
  //入力を受け取る
  int n;cin >> n;
  vector<int>a(n);
  for(int i = 0;i<n;i++){
    cin >> a[i];
  }
  //setを宣言する
  set<int>s;
  for(int i = 0;i<n;i++){
    s.insert(a[i]);
  }
  
  bool ans = false;
  for(int i = 0;i<n;i++){
    if(s.count(a[i]+3)&&s.count(a[i]+6)){
      ans = true;
    }
  }
  
  if(ans)cout << "Yes" << endl;
  else cout << "No" << endl;
}

提出コード(C++)

posted:
last update: