Heavy Light Decomposition
Note
1.DFS1
mark all the depth
mark fathers
mark the heavy/light children
mark the size of each subtree
void dfs1(long long pos, long long f, long long depth){
dep[pos] = depth;
fat[pos] = f;
sz[pos] = 1;
long long maxi = -1;
for (long long v : adj[pos]){
if (v == f) continue;
dfs1(v,pos,depth+1);
sz[pos]+=sz[v];
if (maxi<sz[v]) {maxi = sz[v];son[pos] = v;}
}
}
2.DFS2
mark the of the members in the base array
record the top of each node
traverse heavy son first then light son
mark the heavy son along the path
give the base array a value
record the id of each node
void dfs2(long long pos, long long top_pos){
id[pos] = ++cnt;
wt[cnt] = num[pos];
top[pos] = top_pos;
if (!son[pos]) return;
dfs2(son[pos],top_pos);
for (long long v : adj[pos]){
if (v==fat[pos] || v==son[pos]) continue;
dfs2(v,v);
}
}
3.make_tree
make segment tree base on the base array
void make_tree(int way, int l, int r){
if (l==r) {seg[way] = wt[l]%p;return;}
int mid = (l+r)/2;
make_tree(way*2,l,mid);
make_tree(way*2+1,mid+1,r);
seg[way] = (seg[way*2]+seg[way*2+1])%p;
}
//push function
void push(int way,int lenn){
lazy[way*2]+=lazy[way];
lazy[way*2+1]+=lazy[way];
seg[way*2]+=lazy[way]*(lenn-(lenn>>1));
seg[way*2+1]+=lazy[way]*(lenn>>1);
seg[way*2]%=p;
seg[way*2+1]%=p;
lazy[way]=0;
}
4.query_up
query base on the segment tree
int query_up(int way, int l, int r, int qlow, int qhigh){
push(way,l,r);
if (qlow<= l && r<=qhigh) return seg[way]%p;
if (l>qhigh || r<qlow) return 0;
int mid = (l+r)/2;
return (query_up(way*2,l,mid,qlow,qhigh) + query_up(way*2+1,mid+1,r,qlow,qhigh))%p;
}
5.query
1) check if they are on the same chain. if Not, add the distance from a node to the top of the chain, and move up
2) repeat step 1 until they are on the same chain
3) query the distance between the nodes based on the base array
int query(int x, int y){
int ans = 0;
while(top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) swap(x,y);
ans = (ans+query_up(1,1,n,id[top[x]],id[x]))%p;
x = fat[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
ans = (ans + query_up(1,1,n,id[x],id[y]))%p;
return ans;
}
6.query_son
query the id[x] plus its size -1 the subtree of a node is consecutive in the base array
int qSon(int x){
return query_up(1,1,n,id[x],id[x]+sz[x]-1);
}
7.update
update normal segment tree (use id as substitution)
void update(int way, int l, int r, int qlow, int qhigh, int val){
push(way,l,r);
if (qlow<=l && r<=qhigh) {
lazy[way] += val;
push(way,l,r);
return;
}
if (l>qhigh || r<qlow) return;
int mid = (l+r)/2;
update(way*2,l,mid,qlow,qhigh,val);
update(way*2+1,mid+1,r,qlow,qhigh,val);
seg[way] = (seg[way*2]+seg[way*2+1])%p;
}
8.update chain
1) check if they are on the same chain. If not, update the chain, and go to the father of the chain head
2) repeat until they are on the same chain
3) update the id of the nodes on the segment tree
void upPath(int x, int y, int val){
while(top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) swap(x,y);
update(1,1,n,id[top[x]],id[x],val);
x = fat[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
update(1,1,n,id[x],id[y],val);
}
9.update_son
update id[x] plus its size -1
void upSon(int x, int val){
update(1,1,n,id[x],id[x]+sz[x]-1,val);
}
optional: LCA
1) check if the two nodes are on the same chain
2) if not, find the one with a deeper head, move it up
3) repeat until they are in the same chain
3) return the one with higher depth
int LCA (int x , int y ) {
int fx = top[x] , fy = top[y] ;
while(fx!=fy) {
if(level[fx]< level[fy]) swap(x,y) , swap(fx ,fy) ;
x = fat[fx] ; fx = top[x];
}
if( level[x] > level[y] ) swap(x,y) ;
return x ;
}
Note to myself
Segment tree is able to support different data structure
Heavy Light Decomposition的更多相关文章
- 树链剖分I 原理
树链剖分(Heavy Light Decomposition, HLD)是一种将对[树上两点间的路径]上[边或点]的[修改与查询]转化到[序列]上来处理的方法. 目的:将树的边或点转化到一个线性结构( ...
- 神奇的树上启发式合并 (dsu on tree)
参考资料 https://www.cnblogs.com/zhoushuyu/p/9069164.html https://www.cnblogs.com/candy99/p/dsuontree.ht ...
- HDU 5111 Alexandra and Two Trees 树链剖分 + 主席树
题意: 给出两棵树,每棵树的节点都有一个权值. 同一棵树上的节点的权值互不相同,不同树上节点的权值可以相同. 要求回答如下询问: \(u_1 \, v_1 \, u_2 \, v_2\):询问第一棵树 ...
- [HNOI2018]毒瘤
Description 从前有一名毒瘤. 毒瘤最近发现了量产毒瘤题的奥秘.考虑如下类型的数据结构题:给出一个数组,要求支持若干种奇奇怪怪的修改操作(比如区间加一个数,或者区间开平方),并支持询问区间和 ...
- Wolfycz的娱乐赛题解
现在不会放题解的!比赛完了我会把题解放上来的 祝大家玩的愉快~ 等会,cnblogs不会显示更新时间?我禁赛我自己 UPD:2018.12.15 欢迎大家爆踩标程- painting 我们考虑转化题意 ...
- [ZJOI2011]道馆之战
Description 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个 ...
- codechef Heavy-light Decompositions
Heavy-light Decompositions Problem Code: HLDOTSSubmit All submissions for this problem are available ...
- ACM/ICPC 之 拓扑排序-反向(POJ3687)
难点依旧是题意....需要反向构图+去重+看题 POJ3687-Labeling Balls 题意:1-N编号的球,输出满足给定约束的按原编号排列的重量序列,如果有多组答案,则输出编号最小的Ball重 ...
- poj1013
题目大意:假造的银币 Sally Jones有一些游客给的银币,但是只有11枚是真正的银币(有一枚是假的),从颜色和大小是无法区分真比还是假币的,但是它的重量和真币是不同的,Sally Jones它是 ...
随机推荐
- HDU 2586 LCA-Tarjan
还是LCA-tarjan算法,跟POJ 1330做法基本类似,只是这个题目要求输出两个点的最短距离,其实利用LCA的性质,就是 两个点分别到最近公共祖先的距离之和 一开始本来想用并查集把路径长度给找出 ...
- gdb 常用选项
gdb 常用选项 help:查看命令帮助,具体命令查询在gdb中输入help + 命令,简写h run:重新开始运行文件(run-text:加载文本文件,run-bin:加载二进制文件),简写r st ...
- leetcode 正则表达式 (动态规划)
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配. '.' 匹配任意单个字符'*' 匹配零个或多个前面的那一个元素所谓匹配,是要涵盖 整个 字符串 s的 ...
- HDU - 6043 KazaQ's Socks(找规律)
题意:有n双袜子,编号1到n,放在衣柜里,每天早晨取衣柜中编号最小的袜子穿,晚上将这双袜子放在篮子里,当篮子里有n-1双袜子时,清洗袜子,直到第二天晚上才洗好,并将洗好的袜子重新放回衣柜. 分析:规律 ...
- 把Ubuntu系统自带的源修改为国内的源,中科大源链接:https://mirrors.ustc.edu.cn/repogen/
https://mirrors.ustc.edu.cn/repogen/ Tips: 可通过 URL 的形式直接下载配置. 例如: https://mirrors.ustc.edu.cn/repoge ...
- Busybox文件系统的移植
相关软件下载地址:http://pan.baidu.com/s/16yo8Y fsc100开发板 交叉编译器:arm-cortex_a8-linux-gnueabi-gcc busybox-1.17. ...
- Mac系统Snail SVN 精简版配置比较、合并工具:Beyond Compare及破解
Mac系统 Beyond Compare及破解 前言 在上一篇文章:Mac系统的SVN客户端:Snail SVN 精简版 介绍了在mac系统中svn客户端使用的是snail svn,但是当我想要把本地 ...
- npm、yarn 简单使用记录
npm.yarn常用命令记录,后续会陆续补充... 经过使用发现yarn再下包是速度快,所以日常以yarn指令应用为主 npm查看仓库地址:npm config get registrynpm设置淘宝 ...
- 五、SAP中定义变量和给变量赋值
一.代码如下: 二.执行效果图,如下:
- C# Socket编程入门
一直没有触及到这一块儿,学习下 在看一个小demo https://www.cnblogs.com/yy3b2007com/p/7476458.html