zoukankan      html  css  js  c++  java
  • CF526G

    OmNom……引起了回忆………………

    我想说,这题真是太神仙了 %%%%%%%%%%%%%%


    首先显然选的每条路径都是以叶子为两端的,而且不在不得已的情况下不会选重复的叶子。那么容易发现,对 (2x) 个叶子,选择它们选出的路径的并,最优也优不过它们生成的虚树。实际上稍微动动脑子就能证明:对任意 (2x) 个叶子,一定存在将它们两两配对选出 (x) 条路径的方式,使得这些路径的并为它们生成的虚树。

    稍微动脑子就能会的(感性)证明:考虑归纳,那么只要证对任意 (2x) 个叶子,一定能找到一对叶子,它们的路径和剩下来 (2x-2) 个叶子生成的虚树的并等于这 (2x) 个叶子生成的虚树。根据虚树的每个非叶节点至少有两个儿子这个性质,这只要分个几类就随便证了,再此不赘述。

    那么询问就转化成了:选出任意 (2y) 个叶子生成的包含 (x) 的虚树,求其中边权和最大的方案。不难想到以 (x) 为根来搞,这样由于虚树必须包含 (x),那么这棵虚树显然是所有叶子到根((x))的路径的并。先不管它们生成的虚树能不能包含 (x),那这不就是攻略那题了吗?长剖随便做。然后如果要符合要求的话,必须满足 (x) 是叶子并且被选或者 (x) 的两个不同儿子子树里都有被选的叶子。这是不一定满足的,但是可以发现只需要进行一次调整即可满足,调整指的是删去一个叶子并加入一个叶子。删去就删当前选的贡献最小的,加入就加贡献最大的。当然具体是什么不用说了,因为这个方法本来就是暴力,过不去。

    瓶颈在于我们每次都搞了个不同的根,而这只可能在离线的时候有效,可以存下来然后换根。我们发现,上述方法中第一个选的那个贡献最大的是一定不会被删的,因为 (2y) 是偶数,要删的话最靠前也是第 (2) 名。而这个贡献最大的显然是根所在长链包含的叶子,也就是到根距离最大的叶子。根据直径的性质,这一定是直径的一个端点!也就是说任选一条直径,每组询问选的最优叶子集合一定包含至少一个端点(有多条直径不用怕,是等效的)。

    于是考虑以两个直径端点分别为根,每次询问在两个方案里分别查询取 (max)。考虑如何查询。我们考虑先选出最优的 (2y-1)(有一个叶子是直径端点(根),已经被选)个叶子,然后再调整使得 (x) 被包含进去。不难发现,这样设根,每组选的叶子的答案也一定是它们到根的路径的并,因为根必须被选。那依然可以长剖,并且只需要进行两次长剖,不像上面那种暴力,竟然想在换根的时候搞不可遗传的长剖。

    那考虑如何调整。如果 (x) 已经被选了(一个节点是否被选,可以预处理出所有长链的排名,然后看所在长链是否排名靠前来常数时间查询),那没事了。否则,将 (x) 加进去(贡献显然是它到往上第一个被选的祖先的距离,可以倍增找到(在无边权时跳长链是根号的,但是这题有边权,不行了))之后,只需要删掉原来的任意一个叶子即可。考虑删掉每个叶子的贡献(当然是负的),那就是到往上第一个子树包含其它被选叶子的祖先的距离啊……那么贡献最大的显然是按贪心最后一个选的,直接调用前缀和就好了;但有一个特殊情况:当 (x) 加入之后,它到往上第一个被选的祖先子树内如果只有一个被选叶子的话,那么按照之前说的,应该还要往上消,但是 (x) 的加入能给它保护到「它到往上第一个被选的祖先」,这个特判一下就好。

    总复杂度是线对,因为有倍增。

    code

    珍爱生命,远离抄袭!
  • 相关阅读:
    13.字符串压缩算法
    12.字符串全部替换指定文本
    46.数字到字符串的转换
    45.切割字符串并精确分配内存
    44.字符串删除指定字符或者字符串
    11.表达式计算对一串加减乘除带括号进行计算
    43.可变参数实现printf
    关于float与double区别
    float,double与long long哪个更大?
    double 与0比较时有个精度问题,有时需精确到小数点后面几位,例如与>0.0001,而不能与>0比较
  • 原文地址:https://www.cnblogs.com/ycx-akioi/p/solution-cf526g.html
Copyright © 2011-2022 走看看