k-tokitoh

2019-06-19

しゃくとり法

D - Enough Array

「いちばん愚直にやると O(n3), 累積和つかっても O(n2)だな」まで考えたところで詰まったので解説みた。

しゃくとり法の存在はなんとなく知っていたが、そうかこういう場合に使うと一気に O(n)にできるんだ。

しゃくとり法のアイデアだけおさえて書いたら AC できた。コードは以下。

n, k = gets.split.map(&:to_i)
aa = gets.split.map(&:to_i)

val = aa[0]
ans = 0
r = 0

(0...n).each do |l|
    val -= aa[l-1] if l > 0
        while r < n - 1 do
        (ans += n-r) && break if val >= k
        r += 1
        val += aa[r]
    end
    if r == n-1
    ans += 1 if val >= k
    end
end

p ans

ここから 2 つ変更を加えてみた。

変更を加えた後のコードが以下。

n, k = gets.split.map(&:to_i)
aa = gets.split.map(&:to_i)

cs = 0
acs = [0]
aa.each{|a| acs << acs[-1] + a}

l = 0
ans = 0

(1..n).each do |r|
  while l < r do
    break if acs[r] - acs[l] < k
    l += 1
  end
  ans += l
end

p ans