zoukankan      html  css  js  c++  java
  • atcoder.keyence2019.contest E-Connecting Cities

    真是道好题啊,当时怎么想都没想出来。。。

    传送门

    简述题意:

    有n个点,每个点有一个权值Ai,连接i,j两个点的代价是 |ijD+Ai+A

    其中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 ightarrow A_{y}-A_{z}-yD+zD<0 ightarrow 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)$

  • 相关阅读:
    python 装饰器
    python 环境迁移之requirements.txt (window环境)
    selenium 元素查找与属性
    pytest+allure(allure-pytest基于这个插件)设计定制化报告
    Capability配置
    python_excel
    python_连接mysql
    MySql_1
    appium_环境搭建
    appium_appium简介
  • 原文地址:https://www.cnblogs.com/2017SSY/p/10265060.html
Copyright © 2011-2022 走看看