zoukankan      html  css  js  c++  java
  • 关于树链剖分 "换根操作" 笔记

    [ ext{前言} ]

    (quad)最近在你谷上做了几道"换根操作"的树链剖分题,觉得有必要记录一下,以免以后忘记了。(如果没有见过这种题的可以去做做P3979 遥远的国度CF916E Jamie and Tree)

    [ ext{关于题目要求的操作} ]

    (quad)相信你已经看过这两道题了(没看过也没有没关系),其实可以发现在一棵树中,只有父亲(祖先),子树,深度,会因为根节点的变化而变化,所以题目一般需要你有换根操作,子树修改操作,求 (LCA) (最近公共祖先),我们分别来考虑一下。(可以看看下面这张图来理解,题目中的图)

    )

    [ ext{换根} ]

    (quad)因为每换一次根,树中的很多信息都会改变,不可能每次换根都跑两便 (dfs) 预处理,所以我们考虑其他方法,对于单纯的换根操作,只需要设置一个全局变量 (root) 来存储根的编号( (root) 初始化为 (1) ,默认以 (1) 为根),对于其他操作,再通过分类讨论 (root) 的位置来进行操作。

    [ ext{LCA(最近公共祖先)} ]

    (quad)因为这题我们肯定用树链剖分解题,所以对于原图( (root==1) )的情况下 (LCA) 的求法肯定是使用树链剖分的(当然如果读者愿意专门打个倍增,那么你们随意)

    (quad)注意:(小写) (lca(x,y)) 表示在以1为根的树中 (x)(y) 的最近公共祖先,(大写) (LCA(x,y)) 表示在以 (root) 为根的树中 (x)(y) 的最近公共祖先。

    il int lca(int x,int y) //模板树链剖分求LCA
    {
      int fx=top[x],fy=top[y];
      while(fx!=fy)
        {
          if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
          x=father[fx];fx=top[x];
        }
      if(dep[x]>dep[y])swap(x,y);
      return x;
    }
    

    (quad)接下来我们就要对 (root) 的位置进行分类讨论了,代码先贴出来给你们看看。

    il int LCA(int x,int y)
    {
      if(dep[x]>dep[y])swap(x,y);
      int xr=lca(x,root),yr=lca(y,root),xy=lca(x,y);
      if(xy==x)
      {
      	if(xr==x){if(yr==y)return y;return yr;}
      	return x;
      }
      if(xr==x)return x;if(yr==y)return y;
      if((xr==root&&xy==yr)||(yr==root&&xy==xr))return root;
      if(xr==yr)return xy;
      if(xy!=xr)return xr;return yr;
    }
    

    (quad)另外我们可以再画几张图来方便理解。

    一.当 (lca(x,y)==x) (可以先按深度调序, (dep[x]<=dep[y]))


    (quad) (1). 情况 (1)(root)(x) 的子树中,也在 (y) 的子树中,即 (lca(x,root)==x) && (lca(y,root)==y) ,此时 (LCA(x,y))(y) ,因为图要反过来看(以 (root) 为根)

    (quad) (2). 情况 (2)(root)(x) 的子树中,但不在 (y) 的子树中,即 (lca(x,root)) ,此时 (LCA(x,y))(lca(y,root))

    (quad) (3). 情况 (3) :其他情况下, (LCA(x,y)) 就是 (x)

    二.当 (lca(x,y)!=x) (因为 (dep[x]<=dep[y]),所以 (lca(x,y)!=y)(x) , (y) 在不同子树上)

    (quad) 1. 情况1:( (lca(x,root)==x) )||( (lca(x,root)==x) ),root在x(或y)的子树中时, (LCA(x,y))(x) (或 (y) ),显然。

    (quad) 2. 情况2:( (lca(x,root)==root) && (lca(x,y)==lca(y,root)) )||( (lca(y,root)==root) && (lca(x,y)==lca(x,root))),即 (root)(x)(y) 的简单路径上时,答案为 (root) 。(也可以用深度判断, ( (lca(x,root)===root) && (dep[root]>=dep[lca(x,y)]) )||( (lca(y,root)==root) && (dep[root]>=dep[lca(x,y)]) ))

    (quad) 3. 情况3: (lca(x,root)==lca(y,root)) ,即 (root) 在上方时,(LCA(x,y))(lca(x,y))

    (quad) 4. 情况4:当 (root)(x)(y) 的链上节点的子树中时, (LCA(x,y)) 为那个链上节点。

    (quad)这样就把树上所有 (root) 位置的情况都考虑到了,不重不漏。

    [ ext{子树修改(查询)} ]

    (quad) 情况 (1) :当 (x=root) 时, (x) 就是此时整棵树的根,那么就是全局修改(查询)。

    (quad) 情况 (2) :当 (root) 在x子树中时,就需要特别判断了,根据图像我们可以发现此时x的真正子树是包括除了 (root) 方向上的子树之外其他所有节点。

    (quad) 情况 (3) :其他情况下 (x) 的子树以 (root) 为根和以 (1) 为根是一样的。

    (quad) 以上就是关于树链剖分 "换根操作" 笔记的全部内容了,如果喜欢,不妨点个赞吧!

  • 相关阅读:
    内存映射
    docstring show under decorator
    eventlet dbpool for postgresql &mysql
    za python
    Install MySQL 5.0 Max on FC3
    vi
    ff chrome tips
    20101004网站部署更新
    sqlalchemy type &elixir type
    20100930网站部署更新日志
  • 原文地址:https://www.cnblogs.com/FarkasW/p/13927581.html
Copyright © 2011-2022 走看看