atcoder.keyence2019.contest E-Connecting Cities
真是道好题啊,当时怎么想都没想出来。。。
简述题意:
有n个点,每个点有一个权值Ai,连接i,j两个点的代价是 |i−j|×D+Ai+Aj
其中D是给定的常数,问把n个点联通的最小代价
- 1≤N≤2×$10^{5}$
- 1≤D≤$10^{9}$
- 1≤Ai≤$10^{9}$
上来就有个简单粗暴的生成树做法,不过边的数量太多了,肯定做不了。。。
我们需要减少待选边的数量,这里题解给了两种做法,分别体会下吧?
分治
通过分治,将问题变小,如果每个点都向分界线另一边连有边的话,分治下来总边数是nlogn的
再进一步考虑分治的特性,在分治过程中总能抵消掉元素的大小关系,在这里自然选择点的标号
这样左边的点对一条边的贡献设为$f(i)=A_{i}-i*D$
对应的右边是$g(j)=A_{j}+j*D$
这样一条边$(i,j)$就是$f(i)+g(j)$,我们找到左边最小的$f(i_{0})$,右边最小$g(j_{0})$,这样一个左边的点一定连向$j_{0}$,右边的连向$i_{0}$
如何证明这样一定可以连通呢?
按照上面的算法,一条$i!=i_{0}$且$j!=j_{0}$的边不被选,而这时候,有三条边会代替这条边被选$(i,j_{0}),(i_{0},j),(i_{0},j_{0})$(他们都比原边小)
你会发现这三条边会优先于$(i,j)$考虑的话,在生成树算法中就可以保证i,j两点联通
进而对于每个跨过中线的点对都联通了,完成了分治的目的
跑完生成树就是一个$O(Nlog^{2}N)$
关于$A_{i}$
将A数组按顺序放好了之后我们假设A两两不同,这里的左右指标号大小
对于x,我们默认考虑A比他小的边,我们可以证明以下两个结论:
- 在x左侧所有A比他小的点中,我们只需考虑边权最小的那个
- 在x右侧所有A比他小的点中,我们只需考虑边权最小的那个
我们先来证第一条。若左侧A比他小的点中最小的边是$(x,y)$,
那么对于每个满足$z<x$且$A_{z}<A_{x}$的z来说,
当$z<y$时,因为$A_{x}+xD>A_{y}+yD$,所以$(x,z)>(y,z)$
当$y<z$时,由$(x,y)<(x,z)$可知有$A_{y}-yD<A_{z}-zD\rightarrow A_{y}-A_{z}-yD+zD<0\rightarrow A_{y}+A_{z}+zD-yD<2A_{z}<A_{z}+A_{x}+xD-zD$
所以$(x,z)>(y,z)$
因此得出对于$(x,z)$有都比他小的两条边$(x,y)$和$(y,z)$代替
所以$(x,z)$并不会作为候选边,第二条的证明是类似的
若有A相等,其实并不会影响太多,比他小的条件改成小于等于也可,
实际上的做法要对A排序,再配合树状数组就可以处理了
这样的话,总边数是的$O(N)$,总复杂度是$O(NlogN)$