深さのある区間DP。
制約の小さな問題は、階層の深いDPである可能性が高いので、組み立て方の自由度が高い分難しい。
大小が関係あるので、桁DPっぽく上の桁から'?'を確定させていきたくなるが、その場合は 「S_i は、S_{i-1} より大きいことが確定しているので次の桁には何を置いてもよい」のか、 「まだ確定していないので次の桁には S_{i-1} 以上の数字を置かないといけない」のか、 管理しないと決められない。
だが、S_{i-1} 自体も、S_{i-2} より大きいことが確定している場合と未確定の場合で、 上の桁の状態が変わり、次の桁における数字も異なってきて、とても上手くまとめて管理できない。
「上位桁から見ていって、k 桁目の前までまだ S_l~S_{r-1} の範囲の大小関係が区別できていない」という状態を管理して、 これを再帰的に分割していくことを考える。
k Sl XXXX ? ??? Sl+1 XXXX ? ??? Sl+2 XXXX ? ??? Sl+3 XXXX ? ??? : Sr-2 XXXX ? ??? Sr-1 XXXX ? ??? ~~~~ 同じ
S_l から続く何個かの k 桁目をまとめて決めると、
k Sl XXXX 4 ??? Sl+1 XXXX 4 ??? : Sx-1 XXXX 4 ??? Sx XXXX ? ??? : Sr-1 XXXX ? ???
[l,x) と [x,r) の区間に分けられ、後者の区間の値に制約を持たせれば、この2区間の間の大小関係は確定する。
k k+1 Sl XXXX 4 ? ?? ┐ Sl+1 XXXX 4 ? ?? │[l, x) が k+1 桁目の前まで同じ : │ Sx-1 XXXX 4 ? ?? ┘ Sx XXXX ? ? ?? ┐[x, r) が k 桁目の前まで同じ : │ただし Sx の k 桁目は '5' 以上 Sr-1 XXXX ? ? ?? ┘
よって、以下の関数を定義してやれば、
上の例は、f(l,r,k,d) を、f(l,x,k+1,0) と f(x,r,k,5) に分割したことになる。
f(0,N,0,0) が答えとなる。ここからはじめて再帰的に答えを求めていく。
何度も同じ係数が呼ばれうるため、f() はメモ化再帰で実装する。
遷移を考えると、
終端条件は、
計算量は、f() の状態数が O(N^2MD)(ただし D は文字種数 =10)、 遷移に O(N) なので、O(N^3MD) となる。
AtCoderのレーティングと似たような設定で題意はわかりやすい。(レーティングの算出方法は違うが)
セグメント木などで区間の“平均”を管理しようと思うと、 [l,r) の和とその長さ r-l を持つことになる。
ただし、「平均がある決まった1つの値 B より大きいか小さいか」の判定だけなら、 載せる値から一律に B を引いておくことで、「区間和が 0 より大きいか小さいか」だけで判定でき、 長さを省略できて楽になる。
b_i=a_i-B とし、b_i をセグメント木で管理する。
今回の問題では、「一番始めに b_1+b_2+...+b_i が 0 以上になる i」を求めたい。
なので、b_i の「先頭からの累積和」と、さらにその「累積和の先頭からの累積MAX」を同時に管理したい。
累積和は b_i の値によって上下するためはじめて 0 以上が出現する位置を特定しづらいが、
累積MAXを取っておけば、それを参照して二分探索が可能になる。
各セグメント木のノードに、(その区間の和, その区間の中での先頭からの累積和のMAX) を載せればよい。
ノード n に対して、それぞれ n[0],n[1] とする。
ノード L と R をマージするとき、
R の部分の累積MAXは、マージすると L の区間和分だけスタート位置がずれるので、L[0]+R[1] で求められる。
クエリ c_i,x_i に対して、更新作業は、b_{ci} の値を (x_i-B,x_i-B) で上書きする、という操作になった。
あとは、累積MAXが最初に 0 以上になる位置を二分探索で求めたい。
セグメント木に区間クエリ [1,i) を何度か投げて i を二分探索してもよいが、それだと1回毎に O(\log^2{N}) かかる。
速い言語なら間に合うかも?だが、制約の大きさから、厳しめに設定してあるように感じる。
ここでは、セグメント木に投げるクエリではなく、直接的にセグメント木上で二分探索を行う。
一度でも累積和が 0 以上となるか否かは根ノードを参照すれば簡単に分かるので、 どこかでは 0 以上となる場合のみを考える。
根以降は、自身より左の区間の総和も含めて累積MAXを計算する必要があるので、
これを繰り返して、n が葉になったらその位置が、累積MAXが最初に 0 以上となる位置となる。
これなら O(\log{N}) で求められ、全体で O(N+Q\log{N}) となる。