ABC233_D – Count Interval

IT

ABC233_D – Count Interval

問題

D - Count Interval
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.

提出

TLE: https://atcoder.jp/contests/abc233/submissions/44695634
AC: https://atcoder.jp/contests/abc233/submissions/44695692

解けたが、もう少し簡単な方法があった

以下、思いついた解法を書く。

累積和を用いる。
累積和Biとすると、以下のようになる。
B1=A1
B2=A1+A2
B3=A1+A2+A3

つまり、BiA1からAiまでの和になっている。
これをみると、A1から連続する部分列の和がわかるので、Kになる部分を探す。
次にA2から始まる部分については、BiA1がKになる部分を探す。
次にA3から始まる部分については、BiA1A2がKになる部分を探す。

のようにすると答えが求められそう。
1から始まる部分を求めるとき、調べる必要があるBiの個数はN個、2ではN1個、…となるのでO(N2)になる。
そこで、mapを使ってBiのうち、どの数字が何個あるかをカウントしておく。
これを使うことでO(N)で求められる。
mapを使うと、i番目以降の和を検索できなるので、全体の和からそれまでの和を引くことで対応した。

最初、mapでなくunordered_multisetを使って実装したがTLEになってしまった。
unordered_multisetのcountは、検索対象をaとして、O(count(a))かかる。
検索対象がt個だとt回かかる。
Biが全て同じ和の時、O(N2)になってしまう。

unordered_multiset::count - cpprefjp C++日本語リファレンス
キーを検索し、コンテナ内に見つかった要素の数を返す。

また、公式解説を見るともっと簡単に求めていた。
mapを使って和を検索するとき、自分はlを固定して計算していたが、公式解説ではrを固定して計算していた。
mapを使うと順番がわからなくなるので、lからrまでを検索する時、 lを固定して計算すると全体の和からi番目までのものを引くことになる。
しかし、rを固定するとr以内の累積和を探索するのみなので、全体からわざわざ引く必要はなくなる。

コメント

タイトルとURLをコピーしました