こんばんは、ぱそきいろ (@takacpu55) / Twitterです。
ABC263のD問題(Left Right Operation)解説の理解が難しかったのでメモを残しておきます。
ちなみに最近土曜日に予定が被ってABC出れない・・・
解説
シンプルに解こうと思ったら問題文に沿ってコードを書けばいい気がします。
(最初の方針はこちらを思いついた)
atcoder.jp
もう一つの解説の式変形が詰まったのでメモを残します。
min[0≤x≤y≤N] (Lx+(cum[y]−cum[x])+R(N−y))
Lx:整数xで置き換えた部分の総和
cum[y]-cum[y]:残った部分の総和
R(N-y):整数yで置き換えた部分の総和
この段階ではminを求めようと思ったらx,yの2変数で探さないといけないのでO(N^2)となります。
=RN+ min[0≤x≤N] (Lx−cum[x]+min[x≤y≤N] (cum[y]−Ry))
定数RNを外に出し、minをx,yで分けてますね。
この中で、min[x≤y≤N] (cum[y]−Ry)の部分はxによらないです。
なので0≤y≤N一度計算して配列に入れておけばO(1)で求めることができます。
よってmin[0≤x≤N]の部分を求めるだけでいいので全体でO(N)で求めることができました。
まとめ
来週はABC参加して4完したい...!
ACしたコード
N,L,R=(map(int,input().split())) a=list(map(int,input().split())) #累積和を求めておく cum=[0] for i in range(N): if i==0: cum.append(a[i]) else: cum.append(a[i]+cum[-1]) N=N+1 ycum=[] for i in range(N): ycum.append(cum[i]-R*(i)) #ここでmin[x≤y≤N] (cum[y]−Ry)を改めて求めておく ycummin=[] for i in range(N-1,-1,-1): if i==N-1: ycummin.append(ycum[i]) else: ycummin.append(min(ycummin[-1],ycum[i])) ycummin.reverse() xcum=[] for i in range(N): xcum.append(R*(N-1)+L*(i)-cum[i]+ycummin[i]) xcum.append(sum(a)) print(min(xcum))