torus711 のアレ

主に競技プログラミングの問題について書きます.PC 以外だと数式が表示されないかもしれないです

AtCoder Beginner Contest 258, D : Trophy

問題概要

 $N$ ステージからなるゲームがある.$i$ 番目のステージは,初回クリアには $A_i + B_i$ 分の時間がかかり,2 回目以降のクリアには $B_i$ 分かかる.$i$ ( $0 < i$ ) 番目 (0-indexed) のステージをプレイするには,$i - 1$ 番目のステージをクリア済みである必要がある.
 ステージを合計 $X$ 回クリアするために必要なプレイ時間の最小値はいくらか?

制約

  • $1 \leq N \leq 2 \times 10^5$
  • $1 \leq A_i, B_i \leq 10^9$
  • $1 \leq X \leq 10^9$

解法

 $i$ 番目 (0-indexed) までのステージだけを使って目標を達成する場合というのを考えてみます.このとき,所要時間への寄与は次の 2 種に分類されます:

  • 各ステージを初回クリアするのにかかる時間
  • 初回クリア分では足りないクリア回数を稼ぐのにかかる時間

後者の方は,この状況下でプレイ可能なステージの内で所要時間が最短なものを周回するのが最適で,その時の周回数は $X - 1 - i$ です.なので上記をそれぞれちゃんと書きつつ名前をつけると,

  • $C_i = \sum_{ 0 \leq j \leq i }( A_j + B_j )$
  • $D_i = \min_{ 0 \leq j \leq i } B_j \times ( X - 1 - i )$

となります.これらを使うと,$i$ 番目までのステージを使う場合の最適なプレイ時間は $C_i + D_i$ なので,答えとしてはこの最小値,$$\min_{ 0 \leq i < N }( C_i + D_i )$$ となります.
 この計算に必要な値はすべて $Theta( N )$ 時間で計算できるので,全体としても $Theta( N )$ 時間となります.

コード

main = do
	[ n, x ] <- readIntegers
	[ as, bs ] <- transpose <$> replicateM ( fromIntegral n ) readIntegers
	let
		as_sum = scanl1 (+) $ zipWith (+) as bs
		min_bs = scanl1 min bs
		repeats = zipWith (*) min_bs [ x - 1, x - 2 ]
		results = zipWith (+) as_sum repeats
	print $ minimum results