2021年3月29日月曜日

CodeChef - Unusual Queries

CodeChef - Unusual Queries

iiの「次の山」は、i<ji<jかつHi<HjH_i < H_jであるような最小のjjである。(→ next greater element) 各山に向かって次の山から辺を張ったグラフは有向森であり、この森にHN+1=H_{N+1}=\inftyに対応する大頂点を加えると頂点N+1N+1を根とする有向木(out-tree)になる。この木をTTとする。この時、クエリはTTの一部を切り取ったグラフの最も長いパスの頂点数を質問していることになる。

  • クエリ(L,R)(L, R)を処理する時、rrRRより小さくしても得しないので、r=Rr = Rを固定してl[L,R]l \in [L, R]について最大値が求まればよい。これは適当な列が得られていればRMQに帰着するはずだが、どうやってその列を得るかが問題となる。
  • 任意のRRについて、dpR\operatorname{dp}_RdpR[i]:=l=i,r=R\operatorname{dp}_R[i] := l=i, r=Rの時の求める値、と定める。このとき、dpR+1\operatorname{dp}_{R+1}dpR\operatorname{dp}_R上のR+1R+1の部分木に含まれる各位置に+1したものになっている。
  • TTの頂点番号はTTの帰りがけ順についているので、部分木への加算はdpR\operatorname{dp}_Rのある区間への加算になっている。

したがって、クエリ先読みができるならdpR\operatorname{dp}_Rを区間max・区間addの遅延セグメント木で持ってRRの昇順に更新しつつ、各RRに対応するクエリをまとめて処理すればよい。満点を取るにはオンラインで処理する必要があるが、これは永続化でできる。

この問題の場合はStarry Sky treeでいいので、普通の永続セグメント木と同じように素朴なpath copyingでできる。


わからなかった。上の方針はEditorialの方針とanubhavdharさんの書き込みのハイブリッドみたいなやつ。