zoukankan      html  css  js  c++  java
  • 【基础操作】树分治详解(点/边分治)

    时隔 $???$ 年,我又回来探望树分治了……

    本文于 2019.5.22 更新,删除了之前写的内容,大家如果要学习这个东西可以去看 IOI2019 论文(虽然那里好像也没有具体证明之类的)。

    点分治套路

    1. 连通块

    第 K 大连通块

    $n$ 个点的树,每个点有一个整数点权,连通块的权值为点权和,求权值非严格第 $k$ 大的连通块。

    子任务1:$nle 20$

    子任务2:$n,kle 1000$

    子任务3:树是一条链,且第 $i$ 条边连接编号为 $i$ 和 $i+1$ 的点

    子任务4:$n,kle 10^5$

    题解

    子任务 $1$

    连通块数量显然不超过点集数量,而点集共有 $2^n-1$ 个(去掉空集)。枚举选取的点集并判断其是否为连通块即可。

    时间复杂度 $O(2^n imes n)$。

    子任务 $3$

    问题转化为:给你一个长度为 $n$ 的序列,求第 $k$ 大子序列。

    用【十二省联考2019 异或粽子】那道题的做法就行,只需要把记录异或和改成记录加法和,线段树即可。

    子任务 $2、4$

    发现给的是树,一般与树有关的奇怪题目都跟点分治有关。

    考虑点分治,不难发现子问题增加了 连通块必须包含重心。

    这样就可以证明,对于树中任意一个连通块,该连通块中至少存在一个点,使得该点为重心的点分树 完全包含这个连通块。具体证明只需要考虑一下 重心是连接两棵点分树的边的一端点 这一性质即可,这里不赘述。

    对于一棵点分树,以重心为根(即这个点的 $dfs$ 序为 $1$),重新给点分树中的点标 $dfs$ 序。然后我们考虑按 $dfs$ 序决策选择哪些点。要求选到的点必须是一个连通块

    那么走到 $dfs$ 序为 $i$ 的点时,决策很显然:

    1. 选这个点,继续决策是否选其子树,即花费 $v_i$ 的代价到 $i+1$($v_i$ 为点权);

    2. 不选这个点,那么这棵子树中的所有点都不能选,即花费 $0$ 的代价到 $i$ 的后戳 $+1$($i$ 的后戳就是 $i$ 号点的出栈时间)。

    可以去论文原题看看画出来是什么样的。

    于是一个连通块就对应唯一一条路径了。

    现在就变成了 $O(nlog{n})$ 个点,$O(nlog{n})$ 条边的 $DAG$ ,求 $k$ 短路的经典问题。

    在给定起点和终点的情况下,k 短路的模板:SDOI2010 魔法猪学院

    这里讲一下具体怎么做:

    预处理出以终点为根的最短路树 $T$,即求出每个点到终点的最短路长度。

    定义一种边集 $E$,存一条从起点到终点的路径上,依次经过哪些非树边。

    开一个小根堆,存若干个边集。

    初始时小根堆里只有一个空集。

    然后查询 $k-1$ 次小根堆的顶(注意只是查询,不弹出顶!)。

    每次查询顶后,设顶边集 $E'$ 尾部的边为 $x$(尾部指边集 $E'$ 上次加入的一条边),有 $2$ 种方法得到一个新边集放入堆:

    1. 将 $x$ 替换为起点相同的下一小非树边

    2. 在 $x$ 的后面接上一条非树边,这条非树边的起点在最短路树 $T$ 中是 $x$ 的终点的祖先或同一点,且这条边是当前顶边集未接过的最大的边(也就是下一大)。

    重复操作 $k-1$ 次后,堆顶就是第 $k$ 短路的边集了。

    这种涵盖全局的维护方式跟【十二省联考2019 异或粽子】那道题的维护方式很相似,大家可以感性思考一下为什么这样是对的(建议先思考一个 $lemma$ 为什么是对的:下一短路径一定只需要在之前某一短路径上撇出去一条非树边)。

    第 $1$ 种方法很好搞,对于每个点,开个 $vector$ 存非树边 并按边权排序即可。

    第 $2$ 种方法就需要给每个点建一个 包含自己所有祖先连出去的非树边的堆。

    把堆可持久化即可,每个点继承其父亲的堆,然后再与自己的堆合并,左偏树合并即可。

    时间复杂度大概是 $O(klog{n})$。

    边分治套路

    1. 多棵树套起来

    两棵树

    给出两棵点数均为 $n$ 的树,求两个点,最大化他们在两棵树上的距离和。

    子任务1:$nle 5000$

    子任务2:对于两棵树,各自的第 $i$ 条边连接编号为 $i$ 和 $i+1$ 的点

    子任务3:对于第一棵树,第 $i$ 条边连接编号为 $i$ 和 $i+1$ 的点;对于第二棵树,树是一条链

    子任务4:对于第一棵树,第 $i$ 条边连接编号为 $i$ 和 $i+1$ 的点

    子任务5:$nle 100000$,边权可以为负

    题解

    【WC 2018】通道

  • 相关阅读:
    WIN10系统如何取消右下角的通知菜单,通知图标
    1.1.6版本Druid连接MSSQLServer 2008 R2报错The query timeout value -1 is not valid. #2210
    第一次使用Android Studio时你应该知道的一切配置(三):gradle项目构建
    CentOS 7 Tomcat服务的安装与配置
    centos7中使用yum安装tomcat以及它的启动、停止、重启
    centos7更改为启动桌面或命令行模式
    gradle新建工程,多项目依赖,聚合工程
    Gradle构建多模块项目(转)
    3分钟搞定SpringBoot+Mybatis+druid多数据源和分布式事务
    Spring MVC+Mybatis 多数据源配置
  • 原文地址:https://www.cnblogs.com/scx2015noip-as-php/p/tree_divide.html
Copyright © 2011-2022 走看看