zoukankan      html  css  js  c++  java
  • 树链剖分

    多日前的博客,放在草稿箱快发霉了,今日来填坑!!!

    老早前听了一位大佬的难题选讲(难车选开)介绍了一下树链剖分,感觉很妙妙,恰好大佬降得蛮详细的,不花多少时间就理解了

    在这里就来介绍一下树链剖分,巩固一下记忆。

    还记得最初听一群大佬在以前难题选讲的时候,就用树链剖分来讲题,结果必然是直接全程懵逼,那时我旁边的宋爷就发誓要学这玩意儿,结果一起看博客又有点懵,没坚持下来。倒是宋爷过了一段时间继续重拾树链剖分,250+行代码强行写出,弄得我心里痒痒的,于是就学呗。。。。

    【树链剖分???】

    树链剖分能实现什么呢,这是我第一个想到的问题,想必初学者也疑问过,下面列举一下模板能干什么:

    操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z

    操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和

    操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z

    操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和

    操作5: 格式: x y 表示求x和y的LCA

    【基础姿势】

     

    1、重儿子:每个节点的子树最大的子节点(如图中标没有红点的节点)

    2、 轻儿子:除去重儿子的节点

    3、重链:以每个轻儿子为起点到重儿子,路径上除起点外都是重儿子(也可以是单个轻儿子  如1—>4—>9—>13—>14)

    4、轻链:除去重链以外的路径

    5、链顶:每条链的起点,一定是轻儿子

    6、树链剖分搜索顺序:优先深搜一个节点的重儿子,再搜其他儿子

    储存结构

    siz[v]  以v为根节点的子树的大小

    fa[v]  节点v的父节点

    son[v]  节点v的重儿子

    top[v]  节点v所在链的链顶

    dep[v]  节点v的深度

    【建树操作】

    1、dfs( )

    第一次dfs我们是按dfs序来操作,更新fa[v] dep[v] siz[v] son[v]

     1 int dfs(int now,int ff,int deep)
     2 {
     3     fa[now]=ff,dep[now]=deep,siz[now]=1;
     4     int ms=-1,maxx=-1;
     5     for(int i=head[now];i!=0;i=edge[i].next)
     6     {
     7         if(edge[i].to!=ff)
     8         {
     9             int gg=dfs(edge[i].to,now,deep+1);
    10             if(maxx<gg)
    11             { maxx=gg,ms=edge[i].to; }
    12             siz[now]+=gg;
    13         }
    14     }
    15     if(ms==-1) son[now]=now;
    16     else son[now]=ms;
    17     return siz[now];
    18 }

    1、dfs2( )

    第二次dfs我们是按树链剖分的顺序来操作,更新top[v]

     1 void dfs2(int now,int tt)
     2 {
     3     cnt++,ord[cnt]=now,idx[now]=cnt,top[now]=tt;
     4     if(son[now]==now) return;
     5     dfs2(son[now],tt);
     6     for(int i=head[now];i!=0;i=edge[i].next)
     7     {
     8         if(edge[i].to!=fa[now]&&edge[i].to!=son[now])
     9             dfs2(edge[i].to,edge[i].to);
    10     }
    11 }

    接下来我们可以开始学习基本操作了(其实觉得LCA更简单,更贴切模板)

    求LCA:点我查看

    树链剖分模板:点我查看

  • 相关阅读:
    不懂就问」CPU 到底是怎么识别代码的?
    StackOverflow经典问题:代码中如何去掉烦人的“!=null"判空语句
    在 Excel 中使用正则表达式进行查找与替换
    从浅入深详解独立ip网站域名恶意解析的解决方案
    CentOS配置防火墙操作实例
    三步解决fiddler升级后https无法通过证书验证问题
    apache http跳转到https代码
    openssl命令行将pfx格式转.key和.crt文件,Apache适用
    宝塔面板常用命令大全!
    CentOS如何挂载硬盘
  • 原文地址:https://www.cnblogs.com/genius777/p/8719043.html
Copyright © 2011-2022 走看看