树上问题总结

前言

​ 暑假里通过托老师的分享,系统的学习了树上的一些操作,发现其中有很多有用的trick,所以总结一下。

托神无敌!

  • 问题形式:批量处理f(dep(lca(x,y)))的问题,f(x)是一个关于x的函数

  • 过程:先树剖,然后将x到根的路径先处理出贡献,(对于不同深度带来不同值,可以在数据结构里体现),然后在对于每一个y,统计其到根的路径上的贡献之和。

  • 原理:x与y的lca正是x到根的路径与y到根的路径的第一个交点,其深度自然是两条路径的重合的长度。

  • 例题:

    m次询问,每次询问给出 l r z,求 i=lrdep[LCA(i,z)]

    ​ ——[LNOI2014]LCA

  • 问题:处理关于树上直径的问题

  • 关键:

    • 任意一个点的最远距离的点一定是直径的某一端点(必须是树才可以
    • 任何一个树的直径中心只会有一个或两个。
  • 例题:

    q次询问,每次求出若干个点的最小联通块的所有可能的直径中心

    ​ ——2021.8.26 test T2

  • 问题:一个路径的权值等于路径上任意点对的权值和,求所有路径的权值和。

  • 关键:对于每个点对计算其贡献次数。

    • 若点对(x,y)没有祖先关系,次数为size[x]×size[y]
    • 若点对(x,y)有祖先关系,设x是y的祖先,次数为(nsize[x]+1)×size[y]
  • 原理,计算包含这两个点对的路径的条数。

  • 例题:

    树上每个节点代表了字典树上的一个节点,记为S(x),一条路径K的权值为

    f(K)=xK,yK,x<yf(LCP(S(x),S(y)))

    求树上所有路径的权值和

    ​ ——Luogu P5439永恒

  • 问题:处理不同位置关系的点对

  • 过程:

    • 所有不具有祖先关系的点对

      void sous(int x,int fa){
      	query();
      	遍历子树;
      	insert();
      }
      
    • 所有具有祖先关系的点对

      void sous(int x,int fa){
      	query();
      	insert()
      	遍历子树;
      	delete();
      }
      
  • 例题

    判断一颗树是否满足1i<jn,gcd(ai,aj)=alca(i,j)

    ​ ——Luogu P7854 GCD Tree

  • 问题:在不重复的情况下,计算多个点到根路径上的点权和。

  • 过程:对点按dfs排序,先计算每个点其路径上的点权和,而重复的部分就是每对相邻的点的lca到根的路径上的点权和,减去即可。

  • 原理:类似建虚树的时候将点按dfs排序一样,在有序的情况下,某个点到根路径与现有的路径重合的部分一定是与dfs次小于他的点的lca到根的路径。

  • 例题:

    利用AC自动机求模式串包含多少模板串。(出现多次算一次)

    ​ ——[SCOI2012]喵星球上的点名

  • 问题:每个点产生的贡献需要单独计算,多次询问求根到x的路径的贡献之和。

  • 过程:先把问题离线到各个节点上,最后遍历一次树,进入节点加上贡献,退出时减掉。可以看成一些具有祖先关系的点对

  • 注意:也可以将不经过根节点的链通过差分变成此类问题。由此也可以扩展成一条路径。

  • 例题:

    给一颗树,树上的边有一个字符,q 次询问:每次给两点 x,y 和一个字符串 str,询问串 str 在从点 x 到点 y 的路径中每条边上的小写字母顺次连接形成的字符串中出现多少次。

    ​ ——2021.7.20 test T2

  • 问题:树上DP,父亲的DP值和儿子DP值相关。需要对每个节点单独钦定一次DP值,求根节点的DP值。

  • 过程:把DP的转移看成矩阵。遍历一遍树,利用矩阵的结合律,用栈维护根到父亲的转移的矩阵积。对每个节点构建出钦定DP值后的矩阵,乘上栈顶的矩阵,这样就可以快速求出该节点DP固定,其他点不变时根节点的DP值。

  • 例题

    有一课树。要把树上的节点加入一个集合S,每个点加入集合的概率为。

    p(u)={0vu.son&uSb[u]other

    每个加入集合的点u会产生贡献,具体为

    uSc[v]vS&vsubtree(u)s[v]

    ,你要确定01序列S的值,使上面的式子的期望最大。

    ​ ——2021.9.13 T3

  • 问题:在树上确定两个关键点,每个点的贡献是距离小的关键点的距离×权值

  • 关键:把每个点到距离最小关键点的路径标记,可以确定有一条边一定不会被标记。因此可以对树划分为两个部分,然后对两颗子树分别考虑贡献。

  • 例题:

    一颗树,在树上确定两个关键点,每个点的贡献是距离小的关键点的距离×该点权值,最小化贡献之和(n103

    ​ ——2021.9.16 T4

  • 问题:每个点有颜色,多次询问求某个点的子树内颜色数。

  • 关键:对每种颜色考虑两个dfs序相邻的点,记为x,y,发现x,yx,y,lcax,y分别产生1,1,1的贡献。

  • 例题

    一个每个点有颜色的树, 多组询问,每次询问给出 u,d,求 u 的子树内深度不超过 depu+d 的点集中的颜色种类数,强制在线。

    ​ ——BZOJ4771 七彩树

  • 问题:对于树上的一个点 x[1,n] ,需要对每一个点i[1,n]去考虑是否满足一个条件p(x,i),且只要p(x,i)=1,那么对于ji的子树,都有p(x,j)=1。定义valx=i[p(x,i)=1p(x,fai)=0],对每一个 xvalx

  • 关键:想办法去除只有父亲为 0 自己为 1 的贡献模式(因为这种方式只能暴力扫整树),我们考虑一颗树,有i=1mdai=2m1dii的度数大小,ai表示这子树中的点。所以1=i=1m(2dai),那么我们只要给每个点的贡献设为2(2di),那么valx=i=1n[p(x,i)=1]×(2di),这样就消去了父亲必须为 0 的限制。

  • 例题

    有一棵树,树上的每个叶子都是出入口。开始时,每个出入口都可以放一个农民(也可以不放)。每个时刻,贝茜和农民都可以移动到相邻的一个结点。如果某一时刻农民与贝茜相遇了(在边上或点上均算),则贝茜将被抓住。抓捕过程中,农民们与贝茜均知道对方在哪个结点。

    请问:对于结点 i(1iN) ,如果开始时贝茜在该结点,最少有多少农民,她才会被抓住。

    ​ ——P4183 [USACO18JAN]Cow at Large P

本文作者:qwq_123

本文链接:https://www.cnblogs.com/qwq-123/p/15906073.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   qwq_123  阅读(216)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起