L - Matrix on SegmentTree
問題文
高橋君は次の問題を解いています。
$N$ 個の行列の列 $X$ が与えられる。左から $i$ 番目の行列は $M_{i-1}$ 行 $M_i$ 列である。
$Q$ 個のクエリが順に与えられる。$i$ 番目のクエリは次のような形式である。
- タイプ $1$:
1 x B
$x$ 番目の行列を $M_{x-1}$ 行 $M_x$ 列の行列 $B$ に更新する。- タイプ $2$:
2 l r
$l$ 番目から $r$ 番目までの行列の行列積を計算し出力する。
高橋君はこの問題に、下記の条件を満たす二分木を用いて答えます。
- $2N-1$ 個の頂点からなり、各頂点には番号 $1,2,\cdots,2N-1$ がついている。
- 各頂点 $i$ は区間 $[L_i, R_i]$ を持つ。
- 頂点 $1$ は根であり、区間 $[1, N]$ を持つ。
- 頂点 $i$ が葉であるときかつそのときに限り $L_i = R_i$ である。
- 葉でない頂点には $c_i, d_i$ の $2$ 個の子が存在する。また、葉でない頂点が持つ区間を $[i, j]$ とすると、この頂点の子が持つ区間は $[i, k]$ と $[k + 1, j]$ である。($i \leq k < j$)
- 各頂点 $i$ は、$M_{L_i-1}$ 行 $M_{R_i}$ 列の行列 $A_i$ を持つ。最初、 $A_i$ は $X_{L_i}$ から $X_{R_i}$ までの行列の行列積に等しい。
更に、高橋君は次のような疑似コードを書きました。次の方法によってクエリを処理します。
- タイプ $1$ のクエリが与えられたとき、
f(1, x, B)
を呼び出し各頂点の持つ行列 $A_i$ を更新する。 - タイプ $2$ のクエリが与えられたとき、
g(1, l, r)
を呼び出し答えを計算する。
fun f($n$, $x$, $B$):
if $[L_n, R_n] = [x, x]$:
$A_n$ = $B$
return
if $x \in [L_{c_n}, R_{c_n}]$:
f($c_n$, $x$, $B$)
if $x \in [L_{d_n}, R_{d_n}]$:
f($d_n$, $x$, $B$)
$A_n$ = mult($A_{c_n}$, $A_{d_n}$)
fun g($n$, $l$, $r$):
if $[L_n, R_n] \subset [l, r]$:
return $A_n$
if $[l, r] \cap [L_{c_n}, R_{c_n}] = \emptyset$:
return g($d_n$, $l$, $r$)
if $[l, r] \cap [L_{d_n}, R_{d_n}] = \emptyset$:
return g($c_n$, $l$, $r$)
return mult(g($c_n$, $l$, $r$), g($d_n$, $l$, $r$))
fun mult($A$, $B$):
$C$ = $O_{A.\mathrm{row},B.\mathrm{col}}$
for $i$ in $[0, A.\mathrm{row})$:
for $j$ in $[0, B.\mathrm{col})$:
for $k$ in $[0, A.\mathrm{col})$:
$C_{i,j}$ += $A_{i,k} * B_{k,j}$
return $C$
ただし、$O_{n,m}$ は $n$ 行 $m$ 列の零行列、$A.\mathrm{row}, A.\mathrm{col}$ はそれぞれ行列 $A$ の行数、列数を表します。
行列積の計算は重いことに気づいた高橋くんは、二分木をうまく決めることで行列積にかかる計算量を最小化することにしました。
具体的には、$x$ 行 $y$ 列の行列と $y$ 行 $z$ 列の行列の行列積を計算するのにかかるコストを $xyz$ として、すべてのクエリを処理するときにかかるコストの総和を最小化したいです。
あなたは与えられるクエリの内容を事前に知っています。高橋君の代わりに二分木をうまく決め、コストの総和の最小値を求めてください。
制約
- $1 \leq N \leq 500$
- $1 \leq M_i \leq 10^4 (0 \leq i \leq N)$
- $1 \leq Q \leq 1000$
- タイプ $1$ のクエリにおいて、$1 \leq x \leq N$
- タイプ $2$ のクエリにおいて、$1 \leq l \leq r \leq N$
- 入力はすべて整数である。
部分点
この問題には、部分点が設定されている。部分点の採点方法については、コンテストトップ を参照すること。
- ($200$ 点)
- $1 \leq N \leq 50$
- ($200$ 点)
- $1 \leq N \leq 200$
- ($400$ 点)
- 追加の制約はない。
入力
入力は以下の形式で標準入力から与えられる。
$N$
$M_0$ $M_1$ $\cdots$ $M_N$
$Q$
$\mathrm{query_1}$
$\mathrm{query_2}$
$\vdots$
$\mathrm{query_Q}$
$\mathrm{query_i}$ は $i$ 番目のクエリを表しており、以下のいずれかの形式で与えられる。
$1$ $x$
$2$ $l$ $r$
行列の列 $X$ や更新される行列 $B$ は入力で与えられないことに注意せよ。
出力
コストの総和としてあり得る最小値を出力せよ。
4
2 3 3 4 5
3
1 2
2 1 3
2 1 2
72
- $(c_1, d_1, L_1, R_1) = (2, 3, 1, 4)$
- $(c_2, d_2, L_2, R_2) = (4, 5, 1, 2)$
- $(c_3, d_3, L_3, R_3) = (6, 7, 3, 4)$
- $(L_4, R_4) = (1, 1)$
- $(L_5, R_5) = (2, 2)$
- $(L_6, R_6) = (3, 3)$
- $(L_7, R_7) = (4, 4)$
とするのが最適です。これは完全二分木をなします。このとき、最初のクエリでは f(1, 2, B)
, f(2, 2, B)
, f(5, 2, B)
が呼び出され、
- 区間 $[1, 1]$ と区間 $[2, 2]$ の表す行列の積
- 区間 $[1, 2]$ と区間 $[3, 4]$ の表す行列の積
が計算されます。コストはそれぞれ $2 \times 3 \times 3 = 18, 2 \times 3 \times 5 = 30$ です。
$2$ 番目のクエリでは、g(1, 1, 3)
, g(2, 1, 3)
, g(3, 1, 3)
, g(6, 1, 3)
が呼び出され、
- 区間 $[1, 2]$ と区間 $[3, 3]$ の表す行列の積
が計算されます。コストは $2 \times 3 \times 4 = 24$ です。
$3$ 番目のクエリでは、g(1, 3, 4)
, g(3, 3, 4)
が呼び出され、行列積の計算はありません。
コストの合計は $30 + 18 + 24 = 72$ であり、コストをこれより小さくすることはできません。
各頂点が持つ行列の初期値の計算にコストがかからないことなどに注意してください。
この入力は部分点 $1,2$ の制約を満たします。
9
3 1 4 1 5 9 2 6 5 3
9
1 9
1 9
1 8
1 2
1 4
1 4
1 3
1 5
1 3
408
タイプ $2$ のクエリがなくても行列を更新する必要があります。
この入力は部分点 $1,2$ の制約を満たします。
10
3310 566 5758 7263 4555 5294 2853 9861 7265 5039 7734
10
1 7
2 3 4
2 4 5
2 3 3
2 6 9
2 8 10
2 4 6
1 6
2 4 7
1 7
1148983422423
出力は $32$ bit 整数型に収まらない可能性があることに注意してください。
この入力は部分点 $1,2$ の制約を満たします。