set
set
型は集合を表す。set
型を使うことで、要素の重複を許さず、要素の追加、削除、検索が高速に行える。set
型は重複を許さないため、既に登録した要素を再び登録しようとしても何も起こらない。(イメージは数学Aの集合)
使い方
例としてset
型の変数をs
とする。
関数 | 機能 | 計算量 |
---|---|---|
set<型> s; | set型の変数s を宣言する | |
s.insert(x); | set型の変数s にx を挿入する | |
s.erase(x); | set型の変数s からx を削除する | |
s.count(x) | set型の変数s にx が含まれている個数を数える | |
s.size() | set型の変数s の要素数を取得する | |
s.empty() | set型の変数s が空かどうかを調べる | |
s.clear() | set型の変数s を空にする | |
*s.begin() | set型の変数s の最小値を取得する | |
*s.rbegin() | set型の変数s の最大値を取得する | |
set<型> s(A.begin(), A.end()); | 配列A をset型の変数s に変換する |
さらに…
- C++20以降では、
s.contains(x)
が使える。(機能はs.count(x)
と同じ)
使い方の例
int
型の例
set<int> s;
for (int i = 1; i <= 5; i++) {
s.insert(i);
}
for (int i = 1; i <= 5; i++) {
if (s.count(i)) {
cout << i << "は含まれています" << endl;
} else {
cout << i << "は含まれていません" << endl;
}
}
-
set
型の変数s
には、1, 2, 3, 4, 5が含まれている。 -
1から5までの整数が含まれているかどうかを調べる。
-
1から5までの整数はすべて含まれているので、
1は含まれています
2は含まれています
3は含まれています
4は含まれています
5は含まれています
と出力される。 -
string
型の例
set<string> s;
s.insert("apple");
s.insert("banana");
s.insert("orange");
if (s.count("apple")) {
cout << "appleは含まれています" << endl;
} else {
cout << "appleは含まれていません" << endl;
}
set
型の変数s
には、apple
,banana
,orange
が含まれている。apple
が含まれているかどうかを調べる。apple
は含まれているので、appleは含まれています
と出力される。
multiset
multiset
型はset
型と同じく集合を表すが、要素の重複を許す。- 使い方は
set
型と同じ。 erase
は、その要素すべてが削除される。- 要素を1つだけ削除したい場合は、
s.erase(s.find(x))
を使う。 multiset
型の場合はs.count()
の計算量がになるので注意。
multiset<int> s;
s.insert(1);
s.insert(1);
s.insert(2);
s.insert(2);
s.insert(3);
s.insert(3);
s.erase(2); // 2を削除
s.erase(s.find(3)); // 3を1つだけ削除
- この場合、
s
には1が2つ, 3が1つ含まれている。
さらに…
- C++20より、
multiset
型でもcontains
が使える。 - 要素が複数含まれる場合、
contains
は高速に動作する。(数えあげる動作がなく「要素があるかないか」だけを考える為)
C++のバージョンについて
C++にはいくつかバージョンがあり、バージョンによって使える機能が異なる。 C++20以降の機能を使いたい場合は、ローカルのg++のオプションを変更し、Atcoderの提出時にバージョンをC++20以上のものを選択する必要がある。
g++ -std=c++2a -o test test.cpp
または
g++ -std=c++20 -o test test.cpp
以上のコマンドでオプションとしてC++20の機能を使うことができる。 ※またAOJではC++17までしか対応していないので、C++20以降の機能を使う場合は注意が必要。
multiset<int> s;
s.insert(1);
s.insert(1);
s.insert(2);
s.insert(2);
s.insert(3);
s.insert(3);
if (s.contains(2)) {
cout << "2は含まれています" << endl;
} else {
cout << "2は含まれていません" << endl;
}
- この場合、
2は含まれています
と出力される。
問題
ヒント
for
で回しながら、対象となる数値がset
に含まれているかどうかを確認しよう
解答例
#include <bits/stdc++.h>
using namespace std;
int main() {
set<int> st;
int ans=0;
for (int i = 1; i <= 5; i++) {
int a;
cin >> a;
if (!st.count(a)) {
ans++;
st.insert(a);
}
}
cout << ans << endl;
}
for
で回しながら、対象となる数値がset
型の変数st
に含まれているかどうかを確認し、含まれていない場合はst
に追加する。st
に追加する際に、追加した数値の個数をカウントする。st
に既に追加されている数字が入力された場合は、if
文以降が無視されるため、カウントされない。
map
map
型は「連想配列」や「辞書」と呼ばれるデータ構造を表す。map
型を使うことで、「特定の値に、ある値が紐付いている」ようなデータを簡単に扱うことができる。
使い方
例としてmap
型の変数をmp
とする。
関数 | 機能 | 計算量 |
---|---|---|
map<キーの型, 値の型> mp; | map型の変数mp を宣言する | |
mp[key] = value; | map型の変数mpにkey とvalue のペアを挿入する | |
mp.erase(key); | map型の変数mp からkey を削除する | |
mp.at(key) | map型の変数mp からkey に対応する値を取得する | |
mp.size() | map型の変数mp の要素数を取得する |
使い方の例
vector
型のfruits
に対して、各要素の出現回数をカウントする。
map<string, int> mp;
vector<string> fruits = { "apple", "banana", "orange", "apple", "banana" };
mp["apple"] = 0; // "apple"に対応する値を0にする
mp["banana"] = 0; // "banana"に対応する値を0にする
mp["orange"] = 0; // "orange"に対応する値を0にする
// fruitsの各要素に対して繰り返す
for (string fruit : fruits) {
// fruitに対応する値を1増やす
mp[fruit]++;
}
cout << mp["apple"] << endl; // 2と出力される
map
型の変数mp
には、apple
,banana
,orange
がキーとして含まれている。fruits
の各要素に対して、キーに対応する値を1増やす。apple
は2回出現しているので、2と出力される。
問題
解答例
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); ++i)
int main() {
int n;
cin >> n;
map<string, int> mp;
vector<string> s(n);
for (int i = 0; i < n; i++) {
cin >> s[i];
mp[s[i]]++;
}
int mx = 0;
string ans;
for (int i = 0; i < n; i++) {
if (mp[s[i]] > mx) {
mx = mp[s[i]];
ans = s[i];
}
}
cout << ans << endl;
}
map
型の変数mp
には、入力されたvector
型のs
の各要素がキーとして含まれている。s
の各要素に対して、キーに対応するmp
の値を1増やす。mp
の各キーに対応する値が最大のものをans
に代入する。
練習問題
set型
初級
- https://atcoder.jp/contests/abc089/tasks/abc089_b
- https://atcoder.jp/contests/abc240/tasks/abc240_b
- https://atcoder.jp/contests/abc164/tasks/abc164_c
中級
- https://atcoder.jp/contests/abc073/tasks/abc073_c
- https://atcoder.jp/contests/abc116/tasks/abc116_b
- https://atcoder.jp/contests/abc291/tasks/abc291_c
上級
- https://atcoder.jp/contests/abc310/tasks/abc310_c
- https://atcoder.jp/contests/abc251/tasks/abc251_c
- https://atcoder.jp/contests/abc294/tasks/abc294_d
map型
初級
- https://atcoder.jp/contests/abc173/tasks/abc173_b
- https://atcoder.jp/contests/abc241/tasks/abc241_b
- https://atcoder.jp/contests/abc261/tasks/abc261_c