B - 旅行の所持金 / Travel Budget Editorial
by
MMNMM
Editorial for printing
旅行が始まる前の高橋君の所持金が \(0\) 円であるときの、\(i\) 日目までの処理がすべて終わった直後の所持金を \(D _ i\) とします \((1\le i\le N)\)。 すると、旅行が始まる前の高橋君の所持金 \(X\) に対して、\(i\) 日目までの処理がすべて終わった直後の所持金は \(X+D _ i\) となります。
問題文中の条件はすべての \(i\) に対して \(X+D _ i\ge0\) であることでした。 これは以下のように変形することができます。\[\begin{aligned}&\bigwedge _ {1\le i\le N}\bigl(X+D _ i\ge0\bigr)\\\iff&\min _ {1\le i\le N}\lbrace X+D _ i\rbrace\ge0\\\iff&X+\min _ {1\le i\le N}D _ i\ge0\\\iff&X\ge-\min _ {1\le i\le N}D _ i=\max _ {1\le i\le N}\lbrace-D _ i\rbrace\end{aligned}\]
よって、求めるものは \(\displaystyle X\ge\max _ {1\le i\le N}\lbrace-D _ i\rbrace\) を満たす \(0\) 以上の整数 \(X\) の最小値です。 制約から各 \(D _ i\) は整数であることがわかるので、これは \(\displaystyle \max\Bigl\lbrace 0,\max _ {1\le i\le N}\lbrace-D _ i\rbrace\Bigr\rbrace\) となり、これを計算することでこの問題を解くことができます。
各 \(D _ i\) は、高橋君の所持金をシミュレートすることで \(O(N)\) 時間で求めることができます。
実装例は以下のようになります。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int N;
cin >> N;
long ans = 0;
long D = 0; // はじめの所持金を 0 円としてシミュレーションする
for (int i = 0; i < N; ++i) {
int A, B;
cin >> A >> B;
D += A; // A 円増やして
D -= B; // B 円減らす
ans = max(ans, -D); // 各 -D (と 0) の最大値が答え
}
cout << ans << endl;
return 0;
}
N = int(input())
ans = 0
D = 0 # はじめの所持金を 0 円としてシミュレーションする
for i in range(N):
A, B = map(int, input().split())
D += A # A 円増やして
D -= B # B 円減らす
ans = max(ans, -D) # 各 -D (と 0) の最大値が答え
print(ans)
posted:
last update:
