树链剖分-学习报告

概要

(这是笔者刚学完趁热写的博客
由于也是初学,所以可能会对初学读者比较友好吧
毕竟你不明白的地方我可能也迷惑过)

学完感觉树链剖分的设计真的很巧妙
其主要用途是压缩树上路径
又是一个n到log的优化

原理

先引定义:

设定每个结点所有儿子中,子树的结点个数最多的儿子为重儿子
重儿子连成的链叫做重链
每条重链深度最小的点叫做重链的链头

能得出一个很重要的结论:

从根出发的任意一条路径经过的重链数不超过logm(m为边数)

这是树链剖分提速的关键
这个结论画个图就能很容易的看出来(路径产生断点必然意味着有一条至少比原路径结点更多的子树)

应用

树链剖分常常和dfs序结合
如果再dfs时先dfs重儿子,重链的dfs序就是连续的
我们就可以一起进行修改
这样就可以用线段树之类的结构进行维护了

实现

那么接下来我们尝试代码实现

dfs

先树上dfs一遍求出每个结点的深度、父亲、子树大小等基本信息
顺便把重儿子也求了

void dfs1(int x,int f){size[x]=1;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==f) continue;dep[to]=dep[x]+1;fa[to]=x;dfs1(to,x);size[x]+=size[to];if(!hson[x]||size[to]>size[hson[x]]) hson[x]=to;}return;
}

再dfs一遍求dfs序和链头
注意先dfs重儿子

void dfs2(int x,int tp){top[x]=tp;dfs[++tot]=x;pos[x]=tot;a[tot]=b[x];if(!hson[x]) return;dfs2(hson[x],tp);for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==fa[x]) continue;if(to==hson[x]) continue;else dfs2(to,to);}return;
}

(dfs数组和pos数组互相映射,按需取食)

修改&查询

dfs之后就要开始干活了
修改和查询其实一个道理
两个点如果链头相同,就说明在同一条重链上
直接对两者之间的dfs区间处理即可
否则就选深度大的那个点,让它往上跳一条链,同时对这条链处理
直到两点在同一条重链上为止
对区间的修改查询当然离不开强大的线段树啦

void roadchange(int x,int y,int v){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);longchange(1,1,tot,pos[top[x]],pos[x],v);x=fa[top[x]];}if(dep[x]<dep[y]) swap(x,y);longchange(1,1,tot,pos[y],pos[x],v);return;
}
ll roadask(int x,int y){ll ans=0;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);ans+=longquery(1,1,tot,pos[top[x]],pos[x]);
//		printf("+=%d %d\n",pos[top[x]],pos[x]);ans%=mod;x=fa[top[x]];}if(dep[x]<dep[y]) swap(x,y);ans+=longquery(1,1,tot,pos[y],pos[x]);
//	printf("+=%d %d\n",pos[y],pos[x]);return ans%mod;
}

线段树

不知道怎么写就点这里吧

细节

这是笔者第一次写的时候遇到的一些小的问题
与你共勉吧

1.线段树访问时应该是dfs序小的写在前,也就是深度小的在前!
2.踩一个坑已经足够,所以没有2了

thanks for reading!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/318575.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

牛客题霸 [拼接所有的字符串产生字典序最小的字符串] C++题解/答案

牛客题霸 [拼接所有的字符串产生字典序最小的字符串] C题解/答案 题目描述 给定一个字符串的数组strs&#xff0c;请找到一种拼接顺序&#xff0c;使得所有的字符串拼接起来组成的字符串是所有可能性中字典序最小的&#xff0c;并返回这个字符串。 题解&#xff1a; 用sort…

今日头条Marketing API小工具(.Net Core版本)

前言由于工作原因&#xff0c;需要用到今日头条的Marketing API做一些广告投放的定制化开发。然后看现在网上也没多少关于头条Marketing API的文章&#xff0c;于是便就有了该篇文章。头条Marketing API主页地址&#xff1a;https://ad.toutiao.com/openapi/index.html。头条Ma…

P6880-[JOI 2020 Final]オリンピックバス【最短路】

正题 题目链接:https://www.luogu.com.cn/problem/P6880 题目大意 给出nnn个点mmm条边的有向图&#xff0c;边有边权和一个翻转权值。 翻转至多一条边使得1−>n−>11->n->11−>n−>1往返的权值加上翻转权值最小。 1≤n≤200,1≤m≤51041\leq n\leq 200,1\…

The 2020 ICPC Asia Macau Regional Contest J. Jewel Grab(数颜色+链表)

J. Jewel Grab Tartarus _Wallace_ 转化询问&#xff1a;对于一个询问 [s,k]&#xff0c;找到一个最长的区间 [s,t]&#xff0c;满足区间中出现次数超过一次的元素&#xff0c;的出现次数减一&#xff0c;的和&#xff0c;不超过 k。 对于该区间[s,t] 区间数颜色&#xff1a;…

牛客题霸 [最大数] C++题解/答案

牛客题霸 [最大数] C题解/答案 题目描述 给定一个数组由一些非负整数组成&#xff0c;现需要将他们进行排列并拼接&#xff0c;使得最后的结果最大&#xff0c;返回值需要是string类型 否则可能会溢出 题解&#xff1a; 将字符串存入vector中然后sort排序&#xff0c;最后将…

模板:割点、桥与双连通

文章目录割点代码桥点双连通分量代码边双连通分量代码割点 和强连通分量十分相似 分为树枝边、前向边和后向边 注意&#xff01; if(x!r&&low[to]>dfn[x]) cut[x]1;这句判断只能在树枝边出现 否则会因为前向边的存在而出错 代码 #include<bits/stdc.h> us…

.NET Core实战项目之CMS 第十章 设计篇-系统开发框架设计

这两天比较忙&#xff0c;周末也在加班&#xff0c;所以更新的就慢了一点&#xff0c;不过没关系&#xff0c;今天我们就进行千呼万唤的系统开发框架的设计。不知道上篇关于架构设计的文章大家有没有阅读&#xff0c;如果阅读后相信一定对架构设计有了更近一部的理解&#xff0…

喝酒、工作与自律

喝酒 自从开始打算品酒之后&#xff0c;家里的小酒数量不断增加&#xff0c;每天晚上喝个15ml&#xff0c;慢慢也能喝出一些区别了。 酱香、清香、浓香的区别还是挺明显的&#xff0c;闻香就能区别出来 浓香里的五粮液特点很明显&#xff0c;闻的时候有粮香&#xff0c;入口后…

51nod1836-战忽局的手段【期望dp,矩阵乘法】

正题 题目连接:http://www.51nod.com/Challenge/Problem.html#problemId1836 题目大意 nnn个点mmm次随机选择一个点标记&#xff08;可以重复&#xff09;&#xff0c;求最后被标记点的期望个数。 1≤n,m≤10181\leq n,m\leq 10^{18}1≤n,m≤1018 解题思路 额开始拿方案数推了…

分析现有 WPF / Windows Forms 程序能否顺利迁移到 .NET Core 3.0

今年五月的 Build 大会上&#xff0c;微软说 .NET Core 3.0 将带来 WPF / Windows Forms 这些桌面应用的支持。当然&#xff0c;是通过 Windows 兼容包&#xff08;Windows Compatibility Pack&#xff09;实现的。为了提前检查你的程序是否能在未来跑在 .NET Core 3.0 上&…

第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明) Stone Games

Stone Games 主席树 Code1 #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N1000010; using lllong long; const ll MAX1000000000ll; int n,a[N],m; struct node {int l,r;ll v; }tree[N*40]; int root[N],c…

路径求和(ybtoj-树形dp)

文章目录题目描述解析代码题目描述 给出一棵带边权的树&#xff0c;求所有至少有一个端点为叶节点的所有简单路径的长度和 解析 换一个角度想 考虑将树分割为AB两部分的一条边会存在于多少条符合条件的路径中&#xff08;也就是边权会考虑多少次&#xff09; 不难发现&#…

51nod1675-序列变换【莫比乌斯反演】

正题 题目连接:http://www.51nod.com/Challenge/Problem.html#problemId1675 题目大意 给出两个长度为nnn的序列a,ba,ba,b&#xff0c;求有多少对x,yx,yx,y满足 gcd(x,y)1且abxbaygcd(x,y)1且a_{b_x}b_{a_y}gcd(x,y)1且abx​​bay​​ 1≤n≤105,1≤ai,bi≤n1\leq n\leq 10^5…

牛客题霸 [子数组最大乘积] C++题解/答案

牛客题霸 [子数组最大乘积] C题解/答案 题目描述 给定一个double类型的数组arr&#xff0c;其中的元素可正可负可0&#xff0c;返回子数组累乘的最大乘积。 题解&#xff1a; 同时记录最大值和最小值&#xff0c;为什么?因为给的元素是存在负数的&#xff0c;当出现负数时…

ML.NET 0.8特性简介

本周.NET生态圈内的更新源源不断&#xff0c;除了.NET Core 2.2&#xff0c;ASP.NET Core 2.2和Entity Framework Core 2.2之外&#xff0c;ML.NET 0.8也一并登上舞台。新的推荐场景ML.NET使用基于矩阵分解(Matrix Factorization)和场感知分解机(Field-aware Factorization Mac…

F-Lucky Pascal Triangle(Lucas+数位dp)

F-Lucky Pascal Triangle issue是fw题解 下面代码TLE了&#xff0c;但是此题数位dp的思想非常值得学习 Lucas的过程相当于把n,mn,mn,m在p进制下的每一位拿出来做组合数 Lucas(n,m,p)∏(nkmk)modp\text{Lucas}(n,m,p)\prod \dbinom {n_k}{m_k} \bmod pLucas(n,m,p)∏(mk​nk​…

树的合并(ybtoj-树上dp)

文章目录题目描述前言解析代码thanks for reading&#xff01;题目描述 前言 全网唯一AC&#xff01;&#xff01;&#xff01; 妙啊 而且还是完全自己想出来的做法 开心 &#xff08;APIO还是没白听&#xff09; 但是思路出来后代码实现十分坎坷 建两个图分别dfs3次那个地方…

牛客题霸 [矩阵元素查找] C++题解/答案

牛客题霸 [矩阵元素查找] C题解/答案 题目描述 已知int一个有序矩阵mat&#xff0c;同时给定矩阵的大小n和m以及需要查找的元素x&#xff0c;且矩阵的行和列都是从小到大有序的。设计查找算法返回所查找元素的二元数组&#xff0c;代表该元素的行号和列号(均从零开始)。保证元…

51nod1821-最优集合【贪心】

正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId1821 题目大意 nnn个可重集合&#xff0c;TTT次询问&#xff0c;询问将集合SxS_xSx​和一个选出大小为kkk的SyS_ySy​的子集合并成的独立集S′SS′满足能够找到一个最大的zzz使得对于任意的正整数i∈[1,z…

.net core中的高效动态内存管理方案

.net core在新增的System.Buffers中引入了一大堆高效内存管理的类&#xff0c;如span和memory、内存池。本文今天这里介绍一个高效动态内存访问方案。ReadOnlySequenceSegment<T>在我们读取数据的过程&#xff0c;很多时候会出现如下场景&#xff1a;不知道数据实际大小一…