树上问题总结

前言

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

托神无敌!

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

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

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

  • 例题:

    有 $m $次询问,每次询问给出 \(l\ r\ z\),求 \(\sum_{i=l}^r dep[LCA(i,z)]\)

    ​ ——[LNOI2014]LCA

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

  • 关键:

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

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

    ​ ——2021.8.26 test T2

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

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

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

  • 例题:

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

    \[f(K)=\sum_{x\in K,y\in K,x<y}f(LCP(S(x),S(y))) \]

    求树上所有路径的权值和

    ​ ——Luogu P5439永恒

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

  • 过程:

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

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

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

    判断一颗树是否满足\(\forall 1 \le i < j \le n,\gcd(a_i, a_j) = a_{\operatorname{lca}(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)= \begin{cases} 0&\forall v\in u.son\&u\in S\\ b[u]&other \end{cases} \]

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

    \[\sum_{u\in S}c[v]\sum_{v\in S\&v\in subtree(u)}s[v] \]

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

    ​ ——2021.9.13 T3

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

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

  • 例题:

    一颗树,在树上确定两个关键点,每个点的贡献是距离小的关键点的距离×该点权值,最小化贡献之和(\(n\le 10^3\)

    ​ ——2021.9.16 T4

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

  • 关键:对每种颜色考虑两个dfs序相邻的点,记为\(x,y\),发现\(x,y\)\(x,y,lca_{x,y}\)分别产生\(1,1,-1\)的贡献。

  • 例题

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

    ​ ——BZOJ4771 七彩树

  • 问题:对于树上的一个点 \(x\in[1,n]\) ,需要对每一个点\(i\in[1,n]\)去考虑是否满足一个条件\(p(x,i)\),且只要\(p(x,i)=1\),那么对于\(j\in i\)的子树,都有\(p(x,j)=1\)。定义\(val_x=\sum_{i}[ p(x,i)=1\land p(x,fa_i)=0]\),对每一个 \(x\)\(val_x\)

  • 关键:想办法去除只有父亲为 \(0\) 自己为 \(1\) 的贡献模式(因为这种方式只能暴力扫整树),我们考虑一颗树,有\(\sum\limits_{i=1}^m d_{a_i}=2m-1\)\(d_i\)\(i\)的度数大小,\(a_i\)表示这子树中的点。所以\(1=\sum\limits_{i=1}^m(2-d_{a_i})\),那么我们只要给每个点的贡献设为\(2(2-d_i)\),那么\(val_x=\sum_{i=1}^n[p(x,i)=1]\times(2-d_i)\),这样就消去了父亲必须为 \(0\) 的限制。

  • 例题

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

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

    ​ ——P4183 [USACO18JAN]Cow at Large P

posted @ 2022-02-17 19:26  qwq_123  阅读(180)  评论(1编辑  收藏  举报