其他分享
首页 > 其他分享> > 好题题集3

好题题集3

作者:互联网

毒瘤思维题汇总1

毒瘤思维题汇总2

好题题集1

好题题集2

Podatki drogowe

给定 \(n\) 个点的树,第 \(i\) 条无向边的边权为 \(n^{p_i}\)。

求第 \(k\) 短的路径长度 \(\mod 10^9 + 7\)。

\(2 \le n \le 25000, 1 \le \frac{n(n-1)}{2}, 1 \le p_i \le n,tl = 7s, ml = 1024MB\)

可以做随机化二分的板子题了(虽然挂了边分治,主席树之类的东西),也可以做权为幂的相关运算的板子题了。

其实 小芈 也可以做板子题了,不过那题卡常。

首先如果边权不大,那么可以直接二分长度,然后边分治(或点分治)判断长度小于等于 \(k\) 的链的数量。可以先边分治,对每对分治区域的那些半条链先排个序,二分的时候遍历每个分治区域,直接双指针扫,复杂度是 \(O(n \log^2 n)\) 的。

考虑边权为 \(n^{p_i}\),永远不可能进位,于是可以主席树维护哈希值加速权值的比较,一次比较是 \(O(\log n)\) 的。

还有,这次不能直接二分长度了,需要用到随机化二分。这种算法适用于二分对象为对于若干点(不太多),每个点有若干点可以匹配,并且那些点是有序的,存在快速找到 \((i,j)\) 权值的算法,要求权值第 \(k\) 大的点对(本题求的是路径,小芈那题求的是区间)。此时,可以随机一个点对 \(mid\),计算小于等于这个点对的点对数量是否到达 \(k\),并顺便算出来每个点在小于等于 \(mid\) 的前提下最大的另一个点是那个,即为 \(ptr_i\)。根据点对数量是否达到 \(k\) 来调整每个点的范围。(具体见代码)

最后还有一点要注意,在二分了较多次之后,需要选择最后一个 \(mid\) 作为答案,因为此时可能会出现较多权值相同的点对,此时最后一个 \(mid\) 很有可能就是答案,而如果随便从某个点的对应区间中选择第一个点的话容易出错。

复杂度:时间 \(O(n \log^3 n)\),空间 \(O(n \log^2 n)\)

关键(伪)代码:

for (int _ = 1; _ <= 55; ++_) {
  随机出一个数 tar 并找到第 tar 个链 记为 (jzp,jzq)
	for (int i = 1; i <= htot; ++i) {//计算 ptr[i] 表示第 i 个点最大能匹配第 ptr[i] 个点。
     根据单调性继承上一个的 ptr[i] 以保证复杂度
     调整 ptr[i] 并计算总的可行链数 cnt
	}
  
	if (cnt == K)	break;
	if (cnt < K) {//小的不够,需要调大
     调整每个点能匹配的上下界
     调整 tot, K
	} else {//可以,尝试调小
     调整每个点能匹配的上下界
     调整 tot, K
	}
}
答案为最后一个 (jzp,jzq)

标签:二分,le,log,分治,题集,好题,mid,权值
来源: https://www.cnblogs.com/JiaZP/p/14465530.html