树链剖分详解及模板

这几天学习了一下树链剖分,顺便写一下我的理解、
早上看了一下别人的讲解,云里雾里,终于算是搞懂了、

树链剖分是解决在树上进行插点问线,插线问点等一系列树上的问题
假如现在给你一棵树,然后没两条边之间有一条权值,有一些操作,1:x—y之间的最大权值是多少,2:改变x—y之间的权值
当前这样的操作有很多,如果直接用暴力的方法的话肯定不行,那么就要想一个好的方法,我们可以想一下能不能借助线段树解决,能不能想一种方法对树上的边进行编号,然后就变成区间了。那么我们就可以在线段树上进行操作了,树链剖分就是这样的一个算法。

当然编号不是简单的随便编号,如果我们进行随便的编号,然后建立一个线段树,如果要更新一个边的权值,是log2(n)的复杂度,而查找的话,我们要枚举x–y的之间的所有的边,假如我们随便以一个点为根节点进行编号,最大的长度是树的直径,这个值本身是比较大的,而在线段树上查找任意一个区间的复杂度也是log2(n),这样查找一次的时间复杂度比直接暴力还要高,所以很明显是不行的。
那么就要想想办法了,我们能不能把x–y之间的一些边一块儿查找,这就是关于树链剖分的重边和轻边,

重边:某个节点x到孩子节点形成的子树中节点数最多的点child之间的边,由定义发现除了叶子节点其他节点只有一条重边
重边是可以放在一块儿更新的,而有

性质:从根到某一点的路径上轻边、重边的个数都不大于logn。
所以这样查找的时间复杂度相当于log2(n)

其实树链剖分就是把边哈希到线段树上的数据结构。
实现的话很简单,用两个dfs处理数数的信息,重边以及轻边,然后就是一些线段树的操作了。

模板“:以spoj 375 为例

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define Del(a,b) memset(a,b,sizeof(a))
const int N = 10005;int dep[N],siz[N],fa[N],id[N],son[N],val[N],top[N]; //top 最近的重链父节点
int num;
vector<int> v[N];
struct tree
{int x,y,val;void read(){scanf("%d%d%d",&x,&y,&val);}
};
tree e[N];
void dfs1(int u, int f, int d) {dep[u] = d;siz[u] = 1;son[u] = 0;fa[u] = f;for (int i = 0; i < v[u].size(); i++) {int ff = v[u][i];if (ff == f) continue;dfs1(ff, u, d + 1);siz[u] += siz[ff];if (siz[son[u]] < siz[ff])son[u] = ff;}
}
void dfs2(int u, int tp) {top[u] = tp;id[u] = ++num;if (son[u]) dfs2(son[u], tp);for (int i = 0; i < v[u].size(); i++) {int ff = v[u][i];if (ff == fa[u] || ff == son[u]) continue;dfs2(ff, ff);}
}
#define lson(x) ((x<<1))
#define rson(x) ((x<<1)+1)
struct Tree
{int l,r,val;
};
Tree tree[4*N];
void pushup(int x) {tree[x].val = max(tree[lson(x)].val, tree[rson(x)].val);
}void build(int l,int r,int v)
{tree[v].l=l;tree[v].r=r;if(l==r){tree[v].val = val[l];return ;}int mid=(l+r)>>1;build(l,mid,v*2);build(mid+1,r,v*2+1);pushup(v);
}
void update(int o,int v,int val)  //log(n)
{if(tree[o].l==tree[o].r){tree[o].val = val;return ;}int mid = (tree[o].l+tree[o].r)/2;if(v<=mid)update(o*2,v,val);elseupdate(o*2+1,v,val);pushup(o);
}
int query(int x,int l, int r)
{if (tree[x].l >= l && tree[x].r <= r) {return tree[x].val;}int mid = (tree[x].l + tree[x].r) / 2;int ans = 0;if (l <= mid) ans = max(ans, query(lson(x),l,r));if (r > mid) ans = max(ans, query(rson(x),l,r));return ans;
}int Yougth(int u, int v) {int tp1 = top[u], tp2 = top[v];int ans = 0;while (tp1 != tp2) {//printf("YES\n");if (dep[tp1] < dep[tp2]) {swap(tp1, tp2);swap(u, v);}ans = max(query(1,id[tp1], id[u]), ans);u = fa[tp1];tp1 = top[u];}if (u == v) return ans;if (dep[u] > dep[v]) swap(u, v);ans = max(query(1,id[son[u]], id[v]), ans);return ans;
}
void Clear(int n)
{for(int i=1;i<=n;i++)v[i].clear();
}
int main()
{//freopen("Input.txt","r",stdin);int T;scanf("%d",&T);while(T--){int n;scanf("%d",&n);for(int i=1;i<n;i++){e[i].read();v[e[i].x].push_back(e[i].y);v[e[i].y].push_back(e[i].x);}num = 0;dfs1(1,0,1);dfs2(1,1);for (int i = 1; i < n; i++) {if (dep[e[i].x] < dep[e[i].y]) swap(e[i].x, e[i].y);val[id[e[i].x]] = e[i].val;}build(1,num,1);char s[200];while(~scanf("%s",&s) && s[0]!='D'){int x,y;scanf("%d%d",&x,&y);if(s[0]=='Q')printf("%d\n",Yougth(x,y));if (s[0] == 'C')update(1,id[e[x].x],y);}Clear(n);}return 0;
}

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

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

相关文章

客户端代理的作用

客户端代理的作用•在对象里做了一个标记–“__type” “ComplexType.Color”•服务器端根据标记选择反序列化的目标类型•可出现“多态”效果aspx<form id"form1"runat"server"><asp:ScriptManager ID"ScriptManager1"runat"ser…

汇编算术运算指令

汇编算术运算指令 8086的算术运算类指令能够对二进制或十进制&#xff08;BCD码&#xff09;数进行加、减、乘、除运算&#xff0c;操作数的数据形式可以是8位或16位的无符号数或带符号数。对于单操作数指令&#xff0c;不允许使用立即数形式&#xff1b;对于双操作数指令…

树链剖分入门讲解

“在一棵树上进行路径的修改、求极值、求和”乍一看只要线段树就能轻松解决&#xff0c;实际上&#xff0c;仅凭线段树是不能搞定它的。我们需要用到一种貌似高级的复杂算法——树链剖分。 树链&#xff0c;就是树上的路径。剖分&#xff0c;就是把路径分类为重链和轻链。 记…

选择模块数据读取

1if(Bname"")2{ 3 Response.Write("<script languagejavascript>alert(错误的链接地址&#xff01;);history.go(-1);</script>"); 4 Response.End(); 5 }6if(Bid106&&Sid!0)7{ 8 //<!-- 标准法规--> 9 if(Sid127…

20160828_第4周周报

写在前面 这个周算是暑假集训的最后一周了&#xff0c;当然&#xff0c;周报还是要照常出的&#xff0c;不过昨天我看到了一些公司的商业的周报模板&#xff0c;于是就模仿着更改一下以后周报的报告风格&#xff0c;以后周报统统采用以下的格式进行&#xff0c;按照本周学习内容…

全国医院排名(2008)

中医学 广州中医药大学南京中医药大学 上海中医药大学中国中医研究院 山东中医药大学长春中医学院 山西省中医药研究院河北医科大学内蒙古医学院 [ 转自铁血社区 http://bbs.tiexue.net/ ]中药学 中国中医研究院成都中医药大学南京中医药大学 上海中医药大学 浙江大学广州中…

任重道远——记2016暑假训练

写在前面 刚开学这几天比较忙碌&#xff0c;昨天课也比较满&#xff0c;然后又打了cf&#xff0c;所以写总结的事情倒是拖了很久&#xff0c;早些时间是想到周天写的&#xff0c;结果周六周天又扣了两天的51nod&#xff0c;好容易今天空课&#xff0c;刚好对前一段的状态做一个…

Terrafugia希望在今年夏天带来真正可飞的Airplane

Terrafugia希望在今年夏天带来真正可飞的Airplane 大家都知道&#xff0c;Terrafugia的汽车飞机混合机种&#xff0c;他是是辆双座的汽车&#xff0c;拥有100-500英里的速度范围&#xff0c;一个独立的无铅汽油储备箱&#xff0c;同时配置有电子计算机&#xff0c;用来在空中飞…

手残脑残 记录仪

说明&#xff1a; 该博文用于记录做题过程中各种脑残/手残的低级问题&#xff0c;如果遇到手残的问题出现超过3次&#xff0c;可自行选择。剁手。。 极限数据&#xff0c;例如 0<n<10000 在做题过程中很容易漏掉边角数据&#xff0c;所以在编写的时候&#xff0c;务必…

四川汶川地震祈福赈灾宣传画、报纸头版精选第二版(超多图)

本篇Key词&#xff1a; 汶川地震祈福图片汶川地震祈福壁纸四川汶川地震祈福赈灾宣传画 四川汶川地震祈福赈灾宣传画 天使 不要害怕&#xff0c;手牵手渡过难关 孩子不哭 生命奇迹 从废墟中站起来 祝福灾区人民 众志成城&#xff0c;抗震救灾 众志成城&#xff0c;抗震救灾2 众…

Nim游戏的一个扩展——51nod 1661 黑板上的游戏+LA 5059 Playing With Stones

前几天做过一道题目&#xff0c;是Nim游戏的一个扩展&#xff0c;也不能说扩展吧&#xff0c;只是说另一种常见的状态。 问题引入&#xff1a; 给定n堆石子&#xff0c;每堆石子有vi&#xff08;1<vi<1e5) 个&#xff0c;每次可以取一堆中的一些石子&#xff0c;使得剩…

【转】三五个人十来条枪 如何走出软件作坊成为开发正规军

自从发了上一篇博文&#xff0c;这几天收到很多朋友的来信。大家从各个开发语言的优缺点和适用领域&#xff0c;一直讨论到设计模式、框架、重构、单元测试&#xff0c;乃至敏捷编程&#xff0c;最后都讨论到了软件开发过程管理&#xff0c;甚至都谈到了盈利模式和中国软件的悲…

2016年湖南省第十二届大学生计算机程序设计竞赛

题目&#xff1a; 任意门 听说这套题目是叉姐出的&#xff0c;感觉呵呵了。。。 据说现场牌都不够发的&#xff01;&#xff01;&#xff01;只能说给湖南省出的题目太强了&#xff0c;不适合新手去做&#xff0c;当然我这种老手也不见得做的多好&#xff0c;出了3题&#xf…

控件中的Events个人理解。

首先&#xff0c;了解一下与事件和委托有关的几个类和属性&#xff1a;Delegate, MulticastDelegate, EventHandler, EventHandlerList, EventHandlerList.ListEntry, Control, ComponentControl的Events属性是由System.ComponentModel.Component 继承而来,它是EventHandlerLis…

告白——一个loser的手记

“真不知道怎么会是这样&#xff1f;” 回味以前的种种&#xff0c;到最后才发觉你是如此的模样&#xff0c;如此的狼狈和破败&#xff0c;如此不堪一击。 你曾经以为和高手的差别不过丝毫&#xff0c;但今天看过来&#xff0c;高手夺得了顶峰&#xff0c;而你确一直在这里徘…

ManualResetEvent用法

ManualResetEvent 允许线程通过发信号互相通信。通常&#xff0c;此通信涉及一个线程在其他线程进行之前必须完成的任务。 public static ManualResetEvent mre new ManualResetEvent(false); ManualResetEvent建立时是把false作为start的初始状态&#xff0c;这个类用于通知另…

2014_anshan_onsite

5070 Twelve Months 5071 Chat 比较长的模拟 5072 Coprime 容斥 同色三角形建模后&#xff0c;转化为互质个数问题 5073 Galaxy 数学题&#xff0c;公式递推和化简 5074 Hatsune Miku dp,分类讨论和递推 5075 Random Inversion Ma…

几种流行的JS框架的选择

目前来看&#xff0c;JS框架以及一些开发包和库类有如下几个&#xff0c;Dojo 、Scriptaculous 、Prototype 、yui-ext 、Jquery 、Mochikit、mootools 、moo.fxAjaxian在2007年底对Ajax工具进行了调查&#xff0c;部分调查结果见下表&#xff08;其中数字为调查者使用该工具的…

2014_beijing_onsite

5112 A Curious Matt 签到&#xff0c;排序题目 5113 Black And White 5*5的方格&#xff0c;dfs剪枝 5114 Collision 线性方程求解 扩展欧几里得 5115 Dire Wolf 简单的区间DP问题。 5116 Everlasting L 5117 Fluorescent …

[转]关于HTTP服务器每个客户端2个连接的限制

这两天猫在家里搞一个多线程的断点续传得C#程序&#xff0c;发现同时只能开2个线程下载&#xff0c;其他的线程一律要等待&#xff0c;这样就导致下载大文件时其他线程经常超时&#xff0c;郁闷好久。今天回公司无意中发现了一个帖子&#xff0c;终于真相大白了&#xff0c; …