【树链剖分学习小记】

//废话 : 在几个月前学习学习线段树的时候碰到了LightOJ 1348, 各种蛋疼, 后来学长和我说了这题是用树链剖分做的, 简单了解了之后就放弃了 - - 。

寒假在家无聊翻出来学学, 略有所得。

资料 : 

http://wenku.baidu.com/view/a088de01eff9aef8941e06c3.html 

http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html


背景题目 : M次询问一棵树u -> v上所有的边权最大值, 可修改边权。

如果常规算法去暴力做的话复杂度为O(M*N) - - 。

树链剖分的目的是 : 将一棵树划分成若干条链,用数据结构去维护每条链,复杂度为O(logN)

一些知识 :

ž将树中的边分为:轻边和重边
ž定义size(X)为以X为根的子树的节点个数。
ž令V为U的儿子节点中size值最大的节点,那么边(U,V)被称为重边,树中重边之外的边被称为轻边。
ž粗边为重边。
ž另外,我们称某条路径为重路径(也叫重链),当且仅当它全部由重边组成。
ž轻边(U,V),size(V) <= size(U)/2。
ž从根到某一点的路径上,不超过O(logN)条轻边,不超过O(logN)条重路径。 没有很犀利的去证明过- 。-

所以我们就按按此把一棵树剖分成一段段的重路径和一条条的轻边 - 。-
查询的时候用线段树等数据结构去维护它, 复杂度为O(N * logN + M * logN * logN) 感觉真实的复杂度应该比它小


写法 : 
1. 用2个dfs初始化出
Son[u] : 节点u的重儿子, 没有(即叶子节点) 则为-1
Fa[u]  : 节点u的父亲节点
Siz[u] :以节点u为根的子树的节点数
Dep[u]:节点u 的深度(在后面比较的时候会用到)
top[u] : 节点u所在的重路径的最上面的节点
w[u] : 节点u所对应的夫边在线段树(or 其他数据结构)中的下标
W[u] :这个是我用来建立线段树的. -.-
注意 : 先在第二个dfs的时候先走重儿子, 再回溯回来走其它的儿子

2 查询 u ----> v路径上的所有边(节点的话只要稍微该点就行了)上的所需要的信息

方法是不停的"翻上去" : 就是一条重路径, 一条轻边的翻上去, 在翻的时候要让Dep[top[v或者u]]大的先翻, 具体看代码
这是我写的一个QTREE那一题的查询函数 (好挫哦- -)
int Find(int a, int b){
    int ans = 0;
    while (top[a] != top[b]){
        int f1 = top[a], f2 = top[b];
        if (Dep[f1] >= Dep[f2]){
            ans = max(ans, query(1, 1, m, w[f1], w[a]));
            a = Fa[f1];
        }else {
            ans = max(ans, query(1, 1, m, w[f2], w[b]));
            b = Fa[f2];
        }
    }
    if (Dep[a] == Dep[b])return ans;
    else if (Dep[a] > Dep[b]){
        return max(ans, query(1, 1, m, w[b]+1, w[a]));
    }else {
        return max(ans, query(1, 1, m, w[a]+1, w[b]));
    }
}


3 题目:
SPOJ QTREE      Query on a tree
经典入门题目, 稍微麻烦的就是它是要保留输入的边的信息,- - 比较喜欢问节点信息的

HDU 3966      Aragorn's Story
一段路径上的节点信息修改,然后询问某一个节点的信息, HDU上好像要手动扩栈

POJ  2763       Housewife Wind
询问路径边权长度只和, 起始节点会变

POJ 3237   Tree
稍微麻烦点的, 询问边权最大值个, 多一个可以把一条路径上的所有边权都换个正负号, 线段树成段更新?lazy操作?。。。
我不会告诉你数据水到暴力修改也行 - - 还有写的时候我lazy写错了 - - 真挫

HYSBZ 2243       染色

HYSBZ 1036       树的统计Count
询问最大的节点权值和节点权值之和

HYSBZ 1146       网络管理Network
询问权值第K大的节点. 主席树? 离散化后二分? 反正我不会...

FZU 2082               过路费
求边权和

LightOJ 1348       Aladdin and the Return Journey
求点权和 ----------- 你个大水题 - 。- 哼



//又是一些废话 : 在做题的时候, 看到各种用动态树(link-cut tree ?  or Dynamic Tree ?)过的秀优越感, **, 动态树真的那么爽吗?  我学还不好吗-.- 、、最后又是一年过去了、、、对自己说 : 码年快乐~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值