ural 2119 tree hull

题意:

给出一棵树,边上有全值,有\(n\)个点,对于一个点集\(A\),求权值最小的subtree包含\(A\)中的所有点. 有\(q\)次询问,每次在集合中加入或删除一个值,问修改后的答案.

\(1\leq n\leq 3\cdot 10^5\)

\(1\leq q\leq 3\cdot 10^5\)

题解:

两个点的情况是找到这两个点的lca,最小代价是lca到这两个点的路径的权值和.

三个点\((x,y,z)\)\((x,y)\)的情况可以求出,加入\(z\)之后找到\(z\)\(x,y\)lca深度最深的一个,然后将\(z\)到lca的路径不重合部分加入答案. (正确是因为\(z\)到祖先的路径是固定的,所以路径的长度越短,答案越优)

那么对于一个固定的集合\(A\),答案就是一次加入点\(x\)\(x\)与加入的每一个点求lca,然后找到深度最深的lca,加入这条路径上无重合部分的答案.

但是时间复杂度是\(O(n^2logn)\)的. 肯定不行.

对于一个集合\(A\),与点\(x\)lca深度越大的点,在dfs序上一定是在\(x\)之前的第一个点和在\(x\)之后的第一个点. 考虑按dfs序一次加入,每一次与需要前面的一个点求lca. 现在的时间复杂度是\(O(nlogn)\). 是不可以的.

\(cost(i)\)表示根节点到点\(i\)上边的权值和. 首先将\(A\)按dfs序从小到大排序.

总代价是\(C=\sum cost(A_i)-cost(lca(A_i,A_{i-1}))\).

但有一个问题,\(i=0\)的时候,没有\(A_{i-1}\),因为每两个点都需要联通,所以\(A_i\)连接的这一条边需要与\(A_{k-1}\)相连,lca要选最大的那个. 所以\(A_{-1}\)成了\(A_{a-1}\).

此时就可以用set维护了,set中第一关键字是dfs序,第二关键字是下表. 插入删除时需要找到前一个和后一个,就可以计算新的答案. 在set的开头和结尾时需要特判一下.

时间复杂度: \(O(nlogn)\)

空间复杂度: \(O(nlogn)\) (lca)

posted @ 2021-06-28 21:50  xyangh  阅读(81)  评论(0)    收藏  举报