はじめに
AtCoder Beginner Contest 172 に参加しました。
AtCoder さん、AtCoder Problems さん、ありがとうございます。
今回のお題
AtCoder Beginner Contest C - Tsundoku
Difficulty: 878
今回のテーマ、累積和 + 二分探索
最初は、動的計画法と考え解いていましたがTLE
を貰い大幅な時間のロス、二分探索に切り替えました。
入力例1ですと、次の表の各行で、机Aと机Bの累積和がK分を超えない本数の最大値を求めます。
1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|
60 | 90 | 120 | 80 | 150 | 80 | 150 |
60 | 90 | 80 | 150 | 80 | 150 | |
60 | 80 | 150 | 80 | 150 | ||
80 | 150 | 80 | 150 |
Ruby
ruby.rb
n, m, k = gets.split.map(&:to_i)
a = gets.split.map(&:to_i)
b = gets.split.map(&:to_i)
c = Array.new(n + 1, 0)
n.times do |i|
c[i + 1] = c[i] + a[i]
end
d = Array.new(m + 1, 0)
m.times do |i|
d[i + 1] = d[i] + b[i]
end
cnt = 0
0.upto(n) do |i|
break if c[i] > k
e = d.bsearch_index{_1 > k - c[i]}
if e.nil?
cnt = i + m if cnt < i + m
else
cnt = i + e - 1 if cnt < i + e - 1
end
end
puts cnt
ruby.rb
c = Array.new(n + 1, 0)
n.times do |i|
c[i + 1] = c[i] + a[i]
end
d = Array.new(m + 1, 0)
m.times do |i|
d[i + 1] = d[i] + b[i]
end
累積和です。
ruby.rb
e = d.bsearch_index{_1 > k - c[i]}
if e.nil?
cnt = i + m if cnt < i + m
else
cnt = i + e - 1 if cnt < i + e - 1
end
二分探索です。配列の最大値を超えた場合、nil
を返しますので、その処理が入っています。
Python
python.py
from sys import stdin
import bisect
def main():
input = stdin.readline
n, m, k = map(int, input().split())
a = list(map(int, input().split()))
b = list(map(int, input().split()))
c = [0] * (n + 1)
for i in range(n):
c[i + 1] = c[i] + a[i]
d = [0] * (m + 1)
for i in range(m):
d[i + 1] = d[i] + b[i]
cnt = 0
for i in range(n + 1):
if c[i] > k:
break
e = bisect.bisect_right(d, k - c[i])
if cnt < i + e - 1:
cnt = i + e - 1
print(cnt)
main()
python.py
e = bisect.bisect_right(d, k - c[i])
if cnt < i + e - 1:
cnt = i + e - 1
二分探索です。配列の最大値を超えた場合、配列の要素数+1
を返します。
Ruby | Python | |
---|---|---|
コード長 (Byte) | 433 | 570 |
実行時間 (ms) | 349 | 246 |
メモリ (KB) | 44860 | 47636 |
まとめ
- ABC 172 C を解いた
- Ruby に詳しくなった
- Python に詳しくなった
参照したサイト
bisect --- 配列二分法アルゴリズム