EducationalCF48 C - Vasya And The Mushrooms
問題
2行n列の畑があり、マスごとに毎秒生えるキノコ🍄の本数が決まっている
最初vasyaは1行1列にいて、キノコ🍄は畑全体に1本も生えていない
1マス移動するのには1秒かかる
全マスをちょうど1回ずつ通り、通る時にそのマスに生えているキノコ🍄を全て収穫するとき、最大で何本のキノコ🍄を収穫できるか求める
解法
各マスを一度しか通れない制約から、動きとしては
1) 下・右・上・右・下・右・上・右・...とカクカク進んでいく
2) 今いるマスから同じ行の右端まで真っ直ぐ進んでからUターンする
この2通りしかできない
1)の順番で進んでいき、各マスで「そのマスに進むまでに収穫してきた本数」と「そのマスから2)のように進んだ時に収穫できる本数」の和で答えを更新して行けばいい
後者は累積和を使えばO(1)で求められる
実装
bu[i]: 1行1列から1行m列まで進み、曲がって2行m列に行き、2行1列まで戻る という道中でi番目に通るマスまでに収穫できるキノコの本数
u[i]: ↑と同じ道中でi番目に通るマスまでの各マスの「毎秒生えるキノコの本数」の和
bd, dは2行1列から右に進んでいく場合
つまり初期位置からすぐに右に直進してUターンする場合の本数がbu[2n-1]
何回かカクカク進んでからUターンすると、カクカクしてる間に経った時間のぶん、その先の畑でbuより多くのキノコが生えてるから、それをuで調整する
#define int long long; int n, a[2][300300], res, bu[600600], u[600600], bd[600600], d[600600]; signed main() { cin >> n; rep(i,2) rep(j,n) cin >> a[i][j]; reps(i,1,n*2) { bu[i] = bu[i-1] + a[i/n][(i/n ? n-1-i%n : i%n)]*i; u[i] = u[i-1] + a[i/n][(i/n ? n-1-i%n : i%n)]; } reps(i,0,n*2) { bd[i] = (i==0 ? 0 : bd[i-1]) + a[(i/n)^1][(i/n ? n-1-i%n : i%n)]*i; d[i] = (i==0 ? 0 : d[i-1]) + a[(i/n)^1][(i/n ? n-1-i%n : i%n)]; } int b = 0; rep(i,n*2) { int r = (i%4==0 || i%4==3 ? 0 : 1), c = i/2; b += a[r][c] * i; int ic = 0; if (r==0) { ic = bu[n*2-1-c-(i%2)] - bu[c]; ic += (u[n*2-1-c-(i%2)] - u[c]) * ((i+1)/2); } else { ic = bd[n*2-1-c-(i%2)] - bd[c]; ic += (d[n*2-1-c-(i%2)] - d[c]) * ((i+1)/2); } chmax(res, b+ic); } cout << res << endl; }