この記事は Competitive Programming (1) Advent Calendar 2020 6 日目の記事です。
昨日の記事はわくさんの 競技プログラミングの作問環境構築(gitとrime編) でした。
C++ の標準ライブラリには便利な関数がたくさんあります。 特に <algorithm> と <numeric> には便利な関数が多いので、その紹介をしようという記事です。
C++ 使いは cpprefjp を読もう!
find
count
fill
unique
reverse
shuffle
sort
lower_bound
upper_bound
min
max
min_element
max_element
next_permutation
など
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 文の中に収まる。 えらい。
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;
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{}
って何?関数オブジェクト というやつ
基本的には
template<class T> struct plus{
T operator()(T a, T b){ return a + b; }
};
のようなものだと思っておくと良い
+
などの演算子はたいてい関数ポインタとして渡せないため、その代わりのもの
plus<int> p;
でオブジェクトを作り、 p(1, 2)
のように関数適用できる
bind
って何?引数に定数を固定したり、複数の引数を 1 つにまとめた関数オブジェクトを生成できる
利用例 :
bind(uniform_int_distribution(1, 100), rng)
で uniform_int_distribution
に乱数生成機を固定できる
2 つの列を変換して総和を取りたいときも transform_reduce
でできるんですね〜
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
のほうが 3 文字短い
vector<int> a(n);
copy_n(istream_iterator<int>(cin), n, a.begin());
istream_iterator
は istream
から入力した結果を返してくれるイテレータ
auto p = istream_iterator<int>(cin)
とすると、
*p
で現在の cin
の位置から整数 1 個を読んだ時の値を返す
p++
で cin
を整数 1 個分進める
ことができる
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}
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 要素に対して何かを計算したい時にも使える
bool palindrome(const string& s){
return equal(s.begin(), s.end(), s.rbegin());
}
vector::erase_if
は残念ながら C++20 から
代わりに remove_if
を使う
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}
利用例 : 前半と後半を入れ替える
https://codeforces.com/contest/1381/submission/87563323
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について書くようです!楽しみ〜
MMNMM さんがどこかの問題で next_permutation
と inner_product
を使ってめちゃくちゃ賢い実装をしていた記憶があるんですが、どこにあるでしょうか……