---
tags: 競プロ
---
# あまり知られていない〈algorithm〉
この記事は [Competitive Programming (1) Advent Calendar 2020](https://adventar.org/calendars/4969) 6 日目の記事です。
昨日の記事はわくさんの [競技プログラミングの作問環境構築(gitとrime編)](https://wakuwinmail.hatenablog.com/entry/2020/12/05/015747) でした。
---
C++ の標準ライブラリには便利な関数がたくさんあります。 特に [<algorithm>](https://cpprefjp.github.io/reference/algorithm) と [<numeric>](https://cpprefjp.github.io/reference/numeric) には便利な関数が多いので、その紹介をしようという記事です。
<span style="font-size: 200%">C++ 使いは cpprefjp を読もう!</span>
## よく使われているやつ
- [`find`](https://cpprefjp.github.io/reference/algorithm/find.html)
指定した値を見つけてくる
- [`count`](https://cpprefjp.github.io/reference/algorithm/count.html)
指定した値を数える
- [`fill`](https://cpprefjp.github.io/reference/algorithm/fill.html)
指定した値を代入する
- [`unique`](https://cpprefjp.github.io/reference/algorithm/unique.html)
重複をなくす
- [`reverse`](https://cpprefjp.github.io/reference/algorithm/reverse.html)
ひっくり返す
- [`shuffle`](https://cpprefjp.github.io/reference/algorithm/shuffle.html)
シャッフルする
- [`sort`](https://cpprefjp.github.io/reference/algorithm/sort.html)
ソートする
- [`lower_bound`](https://cpprefjp.github.io/reference/algorithm/lower_bound.html)
二分探索する
- [`upper_bound`](https://cpprefjp.github.io/reference/algorithm/upper_bound.html)
二分探索する
- [`min`](https://cpprefjp.github.io/reference/algorithm/min.html)
最小値を返す
- [`max`](https://cpprefjp.github.io/reference/algorithm/max.html)
最大値を返す
- [`min_element`](https://cpprefjp.github.io/reference/algorithm/min_element.html)
最小値のイテレータを返す
- [`max_element`](https://cpprefjp.github.io/reference/algorithm/max_element.html)
最大値のイテレータを返す
- [`next_permutation`](https://cpprefjp.github.io/reference/algorithm/next_permutation.html)
次の順列を作る
など
## 全て / いずれかの要素が条件を満たすか調べたい時
- [`all_of`](https://cpprefjp.github.io/reference/algorithm/all_of.html)
- [`any_of`](https://cpprefjp.github.io/reference/algorithm/any_of.html)
- [`none_of`](https://cpprefjp.github.io/reference/algorithm/none_of.html)
[ABC155-B Papers, Please](https://atcoder.jp/contests/abc155/tasks/abc155_b)
```cpp
if(all_of(A.begin(), A.end(), [](int x){ return x % 2 || x % 3 == 0 || x % 5 == 0; }))
puts("APPROVED");
else puts("DENIED");
```
flag を持って、 for 文回して、そのあと if 文を書かないといけなかったのが全部 if 文の中に収まる。 えらい。
## 条件を満たすものの個数を数えたい時
- [`count_if`](https://cpprefjp.github.io/reference/algorithm/count_if.html)
[ABC182-B Almost GCD](https://atcoder.jp/contests/abc182/tasks/abc182_b)
```cpp
int ans, max = 0;
for(int k = 2; k <= 1000; k++){
if(chmax(max, count_if(A.begin(), A.end(), [k](int x){ return x % k == 0; })))
ans = k;
}
cout << ans << endl;
```
## 変換して総和を取りたいとき
- [`transform_reduce`](https://cpprefjp.github.io/reference/numeric/transform_reduce.html)
[ABC180-B Various distances](https://atcoder.jp/contests/abc180/tasks/abc180_b)
```cpp
long D1 = transform_reduce(x.begin(), x.end(), 0L, plus{}, abs<long>);
long D2 = transform_reduce(x.begin(), x.end(), 0L, plus{}, bind(multiplies{}, placeholders::_1, placeholders::_1));
long D3 = transform_reduce(x.begin(), x.end(), 0L, [](long a, long b){ return max(a, b); }, abs<long>);
// const T& max(const T&, const T&) と const T& max(initializer_list<T>) の 2 種類あるので max<long> とはできない
cout << D1 << endl;
cout << sqrt(D2) << endl;
cout << D3 << endl;
```
#### `plus{}` って何?
[関数オブジェクト](https://cpprefjp.github.io/reference/functional.html) というやつ
基本的には
```cpp
template<class T> struct plus{
T operator()(T a, T b){ return a + b; }
};
```
のようなものだと思っておくと良い
`+` などの演算子はたいてい関数ポインタとして渡せないため、その代わりのもの
`plus<int> p;` でオブジェクトを作り、 `p(1, 2)` のように関数適用できる
#### `bind` って何?
- [`bind`](https://cpprefjp.github.io/reference/functional/bind.html)
引数に定数を固定したり、複数の引数を 1 つにまとめた関数オブジェクトを生成できる
利用例 :
`bind(uniform_int_distribution(1, 100), rng)` で [`uniform_int_distribution`](https://cpprefjp.github.io/reference/random/uniform_int_distribution.html) に乱数生成機を固定できる
## ハミング距離を求めたい時
2 つの列を変換して総和を取りたいときも [`transform_reduce`](https://cpprefjp.github.io/reference/numeric/transform_reduce.html) でできるんですね〜
[ABC177-B Substring](https://atcoder.jp/contests/abc177/tasks/abc177_b)
```cpp
int ans = INF;
for(auto p = S.begin(); S.end() - p >= T.size(); p++){
chmin(ans, transform_reduce(T.begin(), T.end(), p, 0, plus{}, not_equal_to{}));
}
cout << ans << endl;
```
#### ちなみに
[`inner_product`](https://cpprefjp.github.io/reference/numeric/inner_product.html) のほうが 3 文字短い
## for 文を使わずに配列に入力する
- [`istream_iterator`](https://cpprefjp.github.io/reference/iterator/istream_iterator.html)
- [`copy_n`](https://cpprefjp.github.io/reference/algorithm/copy_n.html)
```cpp
vector<int> a(n);
copy_n(istream_iterator<int>(cin), n, a.begin());
```
[`istream_iterator`](https://cpprefjp.github.io/reference/iterator/istream_iterator.html) は `istream` から入力した結果を返してくれるイテレータ
`auto p = istream_iterator<int>(cin)` とすると、
`*p` で現在の `cin` の位置から整数 1 個を読んだ時の値を返す
`p++` で `cin` を整数 1 個分進める
ことができる
## 累積和をとりたいとき
- [`exclusive_scan`](https://cpprefjp.github.io/reference/numeric/exclusive_scan.html)
```cpp
vector<int> A = {1, 2, 3, 4};
A.push_back(0);
exclusive_scan(A.begin(), A.end(), A.begin());
// A == {0, 1, 3, 6, 10}
```
## 累積和の逆操作をしたいとき
- [`adjacent_difference`](https://cpprefjp.github.io/reference/numeric/adjacent_difference.html)
```cpp
vector<int> A = {0, 1, 3, 6, 10}, B(5);
adjacent_difference(A.begin(), A.end(), B.begin());
// B == {0, 1, 2, 3, 4}
```
#### ちなみに
隣接 2 要素に対して何かを計算したい時にも使える
## 回文かどうか判定したい時
- [`equal`](https://cpprefjp.github.io/reference/algorithm/equal.html)
```cpp
bool palindrome(const string& s){
return equal(s.begin(), s.end(), s.rbegin());
}
```
## 条件を満たすもの全てを削除したい時
[`vector::erase_if`](https://cpprefjp.github.io/reference/vector/vector/erase_if_free.html) は残念ながら C++20 から
代わりに [`remove_if`](https://cpprefjp.github.io/reference/algorithm/remove_if.html) を使う
```cpp
vector<int> A = {0, 1, 3, 0, 5, 0};
A.erase(remove_if(A.begin(), A.end(), logical_not{}), A.end());
// A == {1, 3, 5}
```
## 配列の要素をずらしたいとき
- [`rotate`](https://cpprefjp.github.io/reference/algorithm/rotate.html)
利用例 : 前半と後半を入れ替える
https://codeforces.com/contest/1381/submission/87563323
```cpp
vector<int> A = {0, 1, 2, 3, 4};
rotate(A.begin(), A.begin() + A.size() / 2, A.end());
// A == {2, 3, 4, 0, 1}
```
## おわりに
言語仕様を把握して実装力を上げよう!
明日は Hyado さんが変なmodについて書くようです!楽しみ〜
<div style="font-size:20%">
MMNMM さんがどこかの問題で `next_permutation` と `inner_product` を使ってめちゃくちゃ賢い実装をしていた記憶があるんですが、どこにあるでしょうか……
</div>