显然地,所有数对可以构成一棵树。
按时间分治,设当前在处理 [s,e] 内的修改,我们注意到每个修改会导致树上一条祖先后代链的数对被删除。
假设每次是从一个点 v 往上删到一点 u,我们不妨将所有 u 的父亲和所有 v 拿出来建出虚树,其余的边都可以扔掉。
途中需要用线段树来维护新增的数对。
直接实现就是 O((N+Q)log2(N+Q)) 的。
然而事实上并不需要显式建树,注意到可以用单调栈来在按 DFS 序遍历的时候(也就是按左端点升序遍历)维护每个点的所有祖先。
可能会好写一点(大概)。
另,zkw 线段树在这题上很有用。
代码(从某份 std 那里抄来了 zkw):
1 |
|