公式

C - 本棚の整理 / Organizing the Bookshelf 解説 by kyopro_friends


この問題は尺取法により解くことができます。

尺取法の基本的な枠組みは以下の通りでした。

while left < N:
  while rightを追加してもOK:
    rightを追加
    right+=1
  /*区間 [left, rihgt) に対するなんらかの処理*/
  leftを縮める
  left+=1

今回の問題では、「rightを追加してもOKか?」の判定のために \(B\) に関する和が、問題に対する答え「面白さの和は?」を求めるために \(A\) に関する和が必要なので、その両方持ちながら尺取法を行えばよいです。

計算量は \(O(N)\) です。

以下の実装例では、 \(l>r\) となる瞬間も存在しますが、今回の問題に対しては正しく動作することを証明できます。

実装例 (C++)

#include<bits/stdc++.h>
using namespace std;

int main(){
  int n;
  long long k;
  cin >> n >> k;
  vector<int>a(n), b(n);
  for(int i=0; i<n; i++) cin >> a[i];
  for(int i=0; i<n; i++) cin >> b[i];

  long long sum_a = 0, sum_b = 0, ans = 0;
  int r = 0;
  for(int l=0; l<n; l++){
    while(r < n && sum_b + b[r] <= k){
      sum_b += b[r];
      sum_a += a[r];
      r++;
    }
    ans = max(ans, sum_a);
    sum_b -= b[l];
    sum_a -= a[l];
  }
  cout << ans << endl;
}

実装例 (Python)

N, K = map(int, input().split())
A = list(map(int, input().split()))
B = list(map(int, input().split()))

sum_A = 0
sum_B = 0
r = 0
ans = 0
for l in range(N):
  while r < N and sum_B + B[r] <= K:
    sum_B += B[r]
    sum_A += A[r]
    r += 1
  ans = max(ans, sum_A)
  sum_B -= B[l]
  sum_A -= A[l]

print(ans)

投稿日時:
最終更新: