2日ぶりです。今日の問題はこちら。
提出コードと考え方
制約が緩いのでループを回してゴリゴリ最大値を見つけることもできますが、累積和というものを利用しましょう。以下では累積和を知らない前提で書きます。
行は「 \(0\) 行目、\(1\) 行目」で表し、 \(i\) 行目のアメの個数の列は \(A_{i,0},A_{i,1},\cdots ,A_{i,N-1}\) で与えられるとします。また、\(A_{i,j}\) を単に \(j\) 番目と呼び、「 \(0\) 番目から \(j\) 番目」を「 \([0,j]\) や\([0,j+1)\) 」のように表します。
\(S_{i,j}\) を「 \(i\) 行目の \([0,j)\) の和」( ただし、\(S_{i,0}=0\) )とします。このとき以下が成り立ちます。
\[S_{i,j+1}=S_{i,j}+A_{i,j}\]
\(j\) についてループを回すと、\(0\) 番目から任意の番号までのアメの総和が配列に記憶されます。
こうすると便利なのは、「 \([j,k]\) の和が求められる」ということです。実際、この値は 「 \(S_{i,k+1}-S_{i,j}\) 」 で求められます。【「 \([0,k]=[0,k+1)\) の和 」 \(-\) 「 \([0,k-1]=[0,k)\) の和」】と考えるとわかりやすいと思います。
問題で考えるべきは【「 \(0\) 行目の \([0,j]\) の和」 \(+\) 「 \(1\) 行目の \([j,N-1]\) の和」】、すなわち
\[S_{0,j+1}+S_{1,N}-S_{1,j}\]
です。
ループを回してこの最大値を探しましょう。
#include <bits/stdc++.h>
using namespace std;
int main(){
int N;
cin >> N;
vector<vector<int>> A(2,vector<int>(N));
for(int i = 0;i < 2;i++){
for(int j = 0;j < N;j++){
cin >> A[i][j];
}
}
vector<vector<int>> S(2,vector<int>(N+1,0));
for(int j = 0;j < N;j++){
S[0][j+1] = S[0][j] + A[0][j];
S[1][j+1] = S[1][j] + A[1][j];
}
int ans = 0;
for(int j = 0;j < N;j++){
ans = max(ans,S[0][j+1] + S[1][N] - S[1][j]);
}
cout << ans << endl;
return 0;
}
コメント