公式
B - りんご収穫 / Apple Harvest 解説
by
B - りんご収穫 / Apple Harvest 解説
by
kyopro_friends
この問題は累積和を用いて解くことができます。
以下、数列の添字は \(0\) から始まるものとします。
収穫作業は行えば行うだけ得なので、収穫作業を行う木の本数は \(M\) としてよいです。
各木から出荷できるりんごの個数を表す数列 \(A\) を、
\(A_i=\begin{cases} H_i & H_i\geq K のとき\\ 0 & H_i < K のとき\\ \end{cases}\)
と定めます。求めるのは「\(A\) の連続する \(M\) 要素の和の最大値は?」となります。
数列 \(S\) を \(A\) の累積和とします。すなわち
\(S_i=\begin{cases} 0 & i=0 のとき\\ S_{i-1}+A_{i-1} & i>0 のとき \end{cases}\)
と定めます。\(S_i\) は、数列 \(A\) の先頭から \(i\) 項の和になります。定義から \(S\) は \(O(N)\) で求めることができます。
このとき、\(A\) の連続する \(M\) 要素の和 \(A_L+A_{L+1}+\dots+A_{L+M-1}\) は \(S_{L+M}-S_{L}\) と \(O(1)\) で求めることができます。よって \(L\) を全探索することで \(O(N)\) で答えを求めることができます。
実装例 (C++)
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, m, k;
cin >> n >> m >> k;
vector<int>h(n);
for(int i=0; i<n; i++) cin >> h[i];
vector<long long>s({0});
for(int i=0; i<n; i++){
int a;
if(h[i] < k){
a = 0;
}else{
a = h[i];
}
s.push_back(s[i] + a);
}
long long ans = 0;
for(int i=m; i<=n; i++){
ans = max(ans, s[i] - s[i-m]);
}
cout << ans << endl;
}
実装例 (Python)
N, M, K = map(int, input().split())
H = list(map(int, input().split()))
S = [0]
for h in H:
a = 0 if h < K else h
S.append(S[-1]+a)
print(max(S[i] - S[i-M] for i in range(M, N+1)))
投稿日時:
最終更新:
