Aizu Online Judge(AOJ)が提供している「プログラミング応用」(ITP2)の8_C問題をC++で解いてみました。
ITP2では、「プログラミングのための基礎ライブラリを獲得します」とあります。トピック#8では、辞書(map コンテナ)を学びます。
問題(8_C: Map: Range Search)
問題はリンク先をご覧ください。
AOJ ITP2 8_C問題: Map: Range Search
Map コンテナについて学びます。
Map コンテナについて
以下は、cpprefjp 様の記事を参考にさせていただきました。
Map コンテナについての概要と主なメソッドは、8_A で紹介しています。
Map コンテナ内部の要素は、小さいものから大きなものへとソートされています。そのため、二分探索で要素を探すことができます。二分探索に関係するメソッドは以下となります。
名前 | 説明 |
lower_bound | 与えられた値より小さくない最初の要素へのイテレータを返す。 |
upper_bound | 特定の値よりも大きい最初の要素へのイテレータを返す。 |
C++ プログラム例(ITP2 8_C)
問題で与えられるクエリに従い、キーを文字列とする辞書 M に対して、以下の操作を行います。8_B と比較してクエリ3が追加されています。
- クエリ0 キーが key で値が x である要素をコンテナ M に挿入する。キーが key である要素がすでに存在している場合は、要素の値を x に更新する。
- クエリ1 キーが key である値を出力する。ただし、そのような要素がない場合は、0 を出力する。
- クエリ2 キーが key である要素をコンテナ M から削除する。
- クエリ3 キーが辞書式順で L 以上、R 以下のキーと値の組順番に出力する。
Map コンテナで提供されているメソッドを、クエリに従い呼び出します。要素を探すために lower_bound と upper_bound メソッドを呼び出します(36-41行目)
#include <iostream>
#include <map>
using namespace std;
int main()
{
map<string, int> M;
int q;
cin >> q;
for (int i = 0; i < q; ++i) {
int command;
cin >> command;
if (command == 0) {
string key;
int x;
cin >> key >> x;
M[key] = x;
} else if (command == 1) {
string key;
cin >> key;
if (M.count(key) == 0) {
cout << 0 << endl;
} else {
cout << M[key] << endl;
}
} else if (command == 2) {
string key;
cin >> key;
M.erase(key);
} else if (command == 3) {
string L, R;
cin >> L >> R;
map<string, int>::iterator it = M.lower_bound(L);
map<string, int>::iterator last = M.upper_bound(R);
while (it != last) {
cout << it->first << " " << it->second << endl;
++it;
}
}
}
return 0;
}
上記プログラムは、AOJ で「AC(Accepted=正解)」と判定されました。
最後に
Map のメソッドとして実行される lower_bound と upper_bound メソッドは、6_C で紹介した std::lower_bound 関数と同じく二分探索を使うため、効率が良いです。
引き続き、ITP2 の問題を紹介していきます。