BSOJ8160口胡
设 \(f[i]\) 表示和第 \(i\) 个外挂相交且右端点大于第 \(i\) 个外挂中,右端点最大的外挂,\(g[i]\) 表示右端点满足上述条件中次大的外挂。
如果他不删除外挂,那么直接按着 \(f[i]\) 倍增,然后跳到某个外挂右端点大于 \(t\) 即可。
具体实现可以将 \(i\) 看做一个 \([i,i]\) 的外挂然后按照上述方式维护。
容易发现路径一定是一段 \(f\) 一段 \(g\) 最后再一段 \(f\)。
于是按照 \(f\) 和 \(g\) 建树,先跳到被 ban 外挂的下面,然后到另外一颗树上面跳到某个节点的 \(f\) 不是被 ban 节点为止,然后回到 \(f\) 继续跳。
这样子是 \(O((n+m)\log n)\) 的。实际上可以做到线性。
首先你需要知道四毛子可以线性 \(k\) 级祖先。并且四毛子可以线性树上并查集。
然后跳到被 ban 外挂的下面可以用四毛子。
然后在 \(g\) 上面跳到非 \(f\) 所在节点,可以使用并查集。具体为将所有 \(f\) 是被 ban 外挂的节点连接其父亲即可。
然后问题变为给定 \((u,k)\) 表示询问 \(u\) 最浅的祖先满足其右端点不小于 \(k\)。
将 \(k\) 从小到大排序,令 \(k\) 增加时重复在 \(g\) 上类似的操作即可。
复杂度 \(O(n+m)\)。
清空可以使用时间戳。