「PA 2019」Podatki drogowe

根据套路考虑二分答案。但是值域十分大,不能直接二分。
\(val(l,r)\)表示\((l,r)\)这条路径的权值,\(va(x)\)表示\(x\)这条路径的权值。
幸运的是,由于路径的条数只有\(n^2\)个,可以随机二分。
维护两条路径\(a,b\)表示现在随机二分的上/下界。
每次我们需要随机到一条路径满足\(va(a)<=va(md)<=va(r)\)
先考虑计算权值\(<=md\)的路径条数。
由于每个数的底数都是\(n\),然而一条路径上最多\(n-1\)条边。
所以考虑一条路径上的权值:\(n^{p_1}...n^{p_n}\),使用一个数组\(a\),把\(a_{p_1}....a_{p_n}\)全部+1。
两条路径\(a,b\)的权值加法相当于对位相加。即对于所有\(i\),把\(a_i+=b_i\)
比较两条路径的长度可以使用可持久化线段树+线段树二分。
显然我们在dfs找到分治中心其他点到分治中心的路径时,统计路径的值可以可持久化线段树。
给数组\(a\)的每一个位置随机一个权值\(b\),设一个节点的答案\(=\)数组内所有\(a_i*b_i\)的和。
两条路径加法后的hash值也可以表示为线段树上所有节点的hash值的对位相加。
在线段树二分时,计算hash值计算当前点的左儿子
这样子可以实现\(O(\log_2n)\)比较两条路径的权值。
考虑点分治。把分治重心到分治连通块的所有路径从小到大排序。
则求出和\(<=md\)的路径的个数是一个two-pointer经典问题。
这样子,我们可以在\(O(n\log_2^2n)\)的时间内算出\(<=md\)的点的个数。
在寻找\(md\)的时候也可以使用类似的算法。
总时间复杂度\(O(n\log_2^3n)\)

posted @ 2020-10-22 12:01  celerity1  阅读(213)  评论(0编辑  收藏  举报