Official

C - Distribution Editorial by blackyuki


まず、\(\mathrm{memo}_1=T_1, \mathrm{memo}_{i+1}=\mathrm{memo}_i+S_i\) という漸化式で定められる \(\mathrm{memo}_i\) が、高橋君が \(1\) 番目のすぬけ君に直接渡した宝石が \(i\) 番目のすぬけ君に初めて届く時刻です。

\(2,3, \ldots ,N\) 番目のすぬけ君に直接渡した宝石が \(i\) 番目のすぬけ君にいつ届くかについても同じように考えます。

これを愚直に実装することで \(O(N^2)\) で解けますが、実行時間に間に合わないため高速化を考えます。

ここですぬけ君が受け取る宝石の中で \(2\) 番目以降の宝石は無視できることに注目して今までの \(N\) 個の計算を一つにまとめると、以下のようなコードになります。

少なくとも \(2N\) 回ループを回さないといけないことに注意してください。

実装例 (Python)

N = int(input())
S = list(map(int, input().split()))
T = list(map(int, input().split()))
for i in range(N*2):
    T[(i+1)%N] = min(T[(i+1)%N], T[i%N] + S[i%N])
for ans in T:
  print(ans)

実装例 (C++)

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

int main(){
    int N; cin >> N;
    vector<int> S(N), T(N);
    for(int i = 0; i < N; i++) cin >> S[i];
    for(int i = 0; i < N; i++) cin >> T[i];
    vector<int> memo = T;
    for(int i = 0; i < N*2; i++) memo[(i+1)%N] = min(memo[(i+1)%N], memo[i%N] + S[i%N]);
    for(int ans: memo) cout << ans << endl;
}

posted:
last update: