LoginSignup
2
1

More than 3 years have passed since last update.

Ruby と Python で解く AtCoder ABC130 D 累積和 二分探索

Last updated at Posted at 2020-05-27

はじめに

AtCoder Problems の Recommendation を利用して、過去の問題を解いています。
AtCoder さん、AtCoder Problems さん、ありがとうございます。

今回のお題

AtCoder Beginner Contest D - Enough Array
Difficulty: 859

今回のテーマ、累積和 + 二分探索

問題文(条件)連続部分列に含まれる全ての要素の値の和は、K 以上である。より累積和を使用することが分かりますが、1≦N≦100_000ですので2重にループを回すとTLEになります。
そこで、累積和は単調増加ですので、計算量を抑えるために二分探索も併用します。

Ruby

ruby.rb
n, k = gets.split.map(&:to_i)
a = gets.split.map(&:to_i)
acc = 0
x = [0] + a.map{|v| acc += v}
cnt = 0
x.each do |y|
  j = x.bsearch_index{|z| z - y >= k}
  if j == nil
    break
  else
    cnt += n - j + 1
  end
end
puts cnt
accumulate.rb
acc = 0
x = [0] + a.map{|v| acc += v}

累積和はここで計算しています。
追記
コメントでいただいたコードに修正しました。

bsearch.rb
  j = x.bsearch_index{|z| z - y >= k}

二分探索ですが、C++ でいうところのlower_boundが、Ruby ではbsearch若しくはbsearch_indexになります。

Python

python.py
from sys import stdin

def main():
    import bisect
    import itertools

    input = stdin.readline
    n, k = map(int, input().split())
    a = list(map(int, input().split()))
    x = [0] + list(itertools.accumulate(a))
    cnt = 0
    for z in x:
        j = bisect.bisect_left(x, k + z)
        if j <= n:
            cnt += n - j + 1
    print(cnt)
main()
accumulate.py
    x = [0] + list(itertools.accumulate(a))

Python では、累積和を求めるaccumulateという関数があります。

bisect.py
        j = bisect.bisect_left(x, k + z)

二分探索ですが、bisect若しくはbisect_left bisect_rightを使用します。
探索する数値が配列に含まれる場合、bisectはその数値の右側、bisect_leftは左側の位置を返します。

for.py
    for z in x:
    for i in range(n):

range()でループを回すとTLEしました。

Ruby Python
コード長 (Byte) 238 377
実行時間 (ms) 165 101
メモリ (KB) 11780 14196

まとめ

  • ABC 130 D を解いた
  • Ruby に詳しくなった
  • Python に詳しくなった

参照したサイト

instance method Array#bsearch
すごいぞitertoolsくん
bisect --- 配列二分法アルゴリズム

2
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1