根据套路考虑二分答案。但是值域十分大,不能直接二分。
设(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(nlog_2^2n))的时间内算出(<=md)的点的个数。
在寻找(md)的时候也可以使用类似的算法。
总时间复杂度(O(nlog_2^3n))