应该说标算的思路很神奇很简单但也很容易被人忽视啊,感谢出题人为这个一般化的问题提供了高效的算法。
题意
给定一张\(n\)个点\(m\)条边的带点权的有向图,以及\(q\)个操作,操作有:
\(1\)、删除一条边。
\(2\)、单点修改点权。
\(3\)、询问某个点所在的强连通分量内前\(k\)大的点权和。
\(n\leq 100000\),\(m,q\leq 200000\)。
题解
显然可以按照套路反过来做,于是现在的一个大问题就是加边并维护强连通分量。
直接维护当前的缩点以后的\(\rm DAG\)似乎不可行,因为目前无法高效的在\(\rm DAG\)上找到从\(x\)到\(y\)的一条路径。
于是换一个思路,考虑求出对于每一条边,它出现并且它所连接的两个点成为强连通分量的时间。如果求出了这个,我们就可以和无向图一样用并查集\(+\)启发式合并完成这道题。
那么我们可以考虑整体二分,对于当前的二分区间\([l,r]\),将出现时间\(\leq (mid=(l+r)/2)\)的边加入图,并求出强连通分量。
然后对这些边进行扫描,如果边的出现时间\(\leq mid\)并且连接的两个点已成为一个强连通分量,那么显然合并时间\(\leq mid\),否则\(>mid\)。
那么递归左右两边,在左半边递归完成后将左半边已完成的强连通分量用并查集维护起来,再递归右半边。
如果采用线段树合并/\(\rm Treap\)合并/\(\rm Splay\)合并,那么后半部分可以做到\(O(n\log n)\),再来分析一下求合并时间的复杂度,并查集一共合并\(O(n)\)次,查询\(O(n\log n)\)次,如果将合并改为直接维护根的启发式合并,那么单次查询就是\(O(1)\)的,而单次修改则是均摊\(O(\log n)\)的,于是求合并时间可以做到\(O(n\log n)\),总复杂度就是\(O(n\log n)\)。然而并不会分析直接路径压缩+按秩合并是不是这个复杂度,哼不管了。
代码太丑了就不放了...