与えられたグラフを根付き森とみなすと、ある頂点を消す操作は、のそれぞれの子の部分木との親側の木とをすべて切り離す操作と考えられる。オイラーツアー(pre-order)上で考えると、部分木は連続した区間に対応しているので、区間を切り貼りすることができればよい(下図)。そこでオイラーツアーを平衡二分木で保持することにする。
平衡二分木にを載せて、さらに遅延更新で加算ができるようにする。町についての処理の流れは次のようになる:
- を含む木(=1つの平衡二分木で表されたオイラーツアー)のすべての頂点の値からを引く。
- のを求めて、以下なら上の二分探索で最小値を取る頂点を探す。が日目にになったと記録し、の値をにセットする(再びにならないようにするため。) がより大きくなるまでこれを繰り返す。
- 上図のようにの隣接頂点に関する部分木をすべて切り離す。
1を行う際に、を含む平衡二分木を得る必要があるが、永続UnionFindを使った。事前に列を逆順に走査しながら頂点をつないでおく。を(正順に)処理する際には、その時点でのに対応する(UnionFind上の)根に平衡二分木を持たせるようにした。(でも、ちゃんと前処理すれば普通のUnionFindでできるか。)
計算量は全体で。
明らかに過剰なデータ構造をごちゃごちゃと貼ってしまった。physics0523さんの解説によると、操作の構造自体が木になっていることを利用できるらしい。なるほど……