人間だけど競プロやる

解けなかった問題を理解できたら記事を投稿します。日本語の解説が見つからなかったもの中心。

ABC253 F問題 Operations on a Matrix

NOMURA プログラミングコンテスト2022(AtCoder Beginner Contest 253)
F問題 Operations on a Matrix


状態が多くて脳が破壊された。
だいたいの情報は両端キューで管理して適宜pop_front()するとすこし楽になる。


まずタイプ1(l,r,x)のクエリによってj列目に足された合計はすぐ求まる。 これを「累積和」と呼ぶことにする(遅延セグ木、FwnwickTreeでimos法)。
タイプ2(i,x)が問題で、タイプ3が来たときに、これより前で最新のタイプ2の更新値だけが影響する。
タイプ3(i,j)が来た時に、「i行目のタイプ2での最後の更新値+現在の累積和[j]-最後のタイプ2が来た時点での累積和[j]」を計算できれば答えが求まる。
しかし愚直にやるとO(MQ)のメモリが必要になり無理。
うまく必要な情報だけを管理したい。

具体的にどうするか。

  • タイプ2(i,x)が来た時

i行目で次のタイプ2のクエリがくるまでの間にあるi行目のタイプ3(i,j)について、両端キュー[i]に現在の累積和[j]を追加する。
i行目の最終更新値[i]=xに更新する。

(事前にi行ごとにタイプ2がくるタイミングを計算しておく(両端キューにいれておく))
(事前にi行ごとにタイプ3を両端キューにいれておく)
((とくにi行目で最初のクエリ2の時)現在のタイプ2が来るまでの間に存在するタイプ3に対応する値を追加しないように注意)

  • タイプ3(i,j)がきたとき

a = 現在の累積和[j]
b= 両端キュー[i].pop_front() または 空なら0
c = 最終更新値[i]
としてa-b+c が求める答え。
(両端キュー[i].pop_front()がi行目で最後にタイプ2が来た時点での、現在のタイプ3に対応するj列目の累積
和になる)


両端キューにいれた値は適宜捨てていくことで、計算量を抑えることができる。