一只兔子对于树链剖分的理解

原创 2016年06月01日 16:30:03

树链剖分是做甚的?

某个早上,一只兔子沿一条不规则的曲线冲过来,问了另一只兔子这个问题。
这只兔子当场开始转圈(这是它的一种癖好)。
兔子新的一天开始了…

0

树链剖分?什么鬼?
不太懂的小兔子向老兔子(场外观众)求援了。
“咳咳,顾名思义,树链剖分嘛,就是把树剖分成链……”
“这不废话吗?”
“……剖分成若干条链,然后把每条链扔进数据结构里维护……”
“等等树链剖分是干吗的?”
“……以解决如把一棵树上同时增减节点x到节点y的权值之类的问题……”
“……”
(太给力了,你的回答完美的解决了我的问题?)(某熊乱入,惊散兔子)

1

树链剖分有俩个东东
重边 轻边
重边:比较重的那边
轻边:比较轻的那边
嗯,老兔子喝了点伏特加(然而并不是广告)(推)
size(x):以节点x为根的子树的节点个数
重边:节点x与其有最大的size值的那个儿子之间的边
轻边:除了重边外的边全是轻边
“为什么要这样做?”
(老兔子爬起)“Just for fun.啊,不是不是为为为为了使链的数目尽量少,省事。”(又自己摔倒)
“好像有道理…”

于是就有了这两个性质
(1)轻边(u,v)中,size(v)<=size(u)/2
(2)从根到某一点的路径上,轻边、重边条数不超过log n。

2

重边轻边好分,不过怎么连成链呢?
我们把重边连起来:从根节点开始,沿着重边往下找,拉成重链,不在这条重链上?那就从这个节点再往下拉一条。
Talking is easy.Show me the…picture.
树链剖分图

3

以下是一些数组

  • 之前的size[]数组
  • 为了区分重边轻边,我们需要ch[]保存重儿子
  • 当然有儿子就有爹——fa[]数组
  • 为了区分边所属的链,我们需要top[]数组,保存该节点的所在链的顶端节点
  • 为了防止搞混编号,我们需要tid[]数组,保存树中每个节点剖分后的新编号;zrank[]数组,保存当前节点在线段树中的位置
  • 嗯我们还需要一个记录深度的dep[]数组,原因…就不用说了…

4

老兔子:”让我翻出70年的雪碧,啊不是15年的代码”

int point[MAX_N],size[MAX_N],top[MAX_N],ch[MAX_N];
int deep[MAX_N],tid[MAX_N],zrank[MAX_N],fa[MAX_N];
int head[MAX_N],to[2*MAX_N],znext[2*MAX_N],edge;//链式前向星

void zinit() {
    memset(head,-1,sizeof(head));
    memset(ch,-1,sizeof(ch));
    num=0;edge=0;
}

void add_edge(int u,int v) {
    to[edge]=v,znext[edge]=head[u],head[u]=edge++;
    to[edge]=u,znext[edge]=head[v],head[v]=edge++;
}

void dfs1(int u,int pa,int d) {
    deep[u]=d;
    fa[u]=pa;
    size[u]=1;
    for(int i=head[u];~i;i=znext[i]) {
        int v=to[i];
        if(v!=pa) {
            dfs1(v,u,d+1);
            size[u]+=size[v];
            if(ch[u]==-1||size[v]>size[ch[u]])
                ch[u]=v;
        }
    }
}

void dfs2(int u,int tp) {
    top[u]=tp;
    tid[u]=++num;
    zrank[tid[u]]=u;
    if(ch[u]==-1) return;
    dfs2(ch[u],tp);
    for(int i=head[u];~i;i=znext[i]) {
        int v=to[i];
        if(v!=ch[u]&&v!=fa[u])
            dfs2(v,v);
    }
}
版权声明:咳,博主原创,需博主许可方能转载。

相关文章推荐

树链剖分

  • 2015年09月22日 16:44
  • 800KB
  • 下载

【算法与数据结构】 树链剖分

  • 2016年07月29日 19:49
  • 919KB
  • 下载

[理解]树链剖分

转载请注明:http://blog.csdn.net/jiangshibiao/article/details/24669751 【原题】 1036: [ZJOI2008]树的统计Count Ti...
  • otowa
  • otowa
  • 2016年02月19日 17:33
  • 865

树链剖分模板

  • 2015年03月05日 08:33
  • 5KB
  • 下载

树链剖分模板题

  • 2015年05月19日 09:38
  • 3KB
  • 下载

一只兔子如何吃掉狼的!

一天,一只兔子在山洞前写文章,一只狼走了过来,问:“兔子啊,你在干什么?”答曰:“写文章。”问:“什么题目?”答曰:“《浅谈兔子是怎样吃掉狼的》。”狼哈哈大笑,表示不信,于是兔子把狼领进山洞.过了一会...

Spoj 375 QTREE1 树链剖分裸题

题目链接:http://www.spoj.com/problems/QTREE/ 题意: T个测试案例 n个点的树 下面n-1条边和边权   change u v 把第u-th给出的边 的边权改为v ...

hdu3966Aragorn's Story(树链剖分+树状数组维护区间)

/***************************************** Author :Crazy_AC(JamesQi) Time :2016 File Nam...

HYSBZ 1036 树的统计Count 树链剖分

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 题意:Description   一棵树上有n个节点,编号分别为1到...

bzoj 4712: 洪水 (树链剖分+DP)

题目描述传送门题目大意:给出一颗树,对于每个节点可以花费val[i]的代价把他堵住,使水无法向下流。每个节点的代价可能会在某时刻增加。对于每个询问,求出某个点的子树中的叶子节点(没有子节点)都没有水的...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一只兔子对于树链剖分的理解
举报原因:
原因补充:

(最多只允许输入30个字)