题目
思路
看完题目之后,很明显这是一道树剖题。为什么这么说呢?
- 他会改变树上两点的路径上的边权。
- 他要查询树上两点的路径上的最大边。
- 他要改变某条边的边权
从这几点来看就是说我们要在树上做区间操作!!!
这里有好多难点:
- 边权是很难使用的,不如将其改为点权
- 如何用树剖出的几条链组成的序列来进行各种操作
这里我们用线段树来进行区间操作,将边权改为“这条边的一个端点到另一个端点的所花费的值”(两个端点为父子节点的关系),这样就可以将边权化为点权。
比如:$u \to v$这条边的值为3,我们可以将它变为p[v]=3;(意思是v到u这条边的边权为3)。
代码
假设树剖之后我们用in[x]表示x这个点的dfs序,id[x]表示x这个编号对应的点(本人英语不好,数组名瞎取的)
之后我就直接给出线段树的操作代码:(别说你连线段树都不懂就来学树剖)
建树
1 | void build(int c,int l,int r){ |
下放懒标记
(注意:这里本人用了两个懒标记,一个是覆盖(lazy),一个是加(add))
1 | void spread(int c){ |
区间加操作
1 | void change1(int c,int l,int r,int x,int y,int k){ |
区间覆盖
1 | void change2(int c,int l,int r,int x,int y,int k){ |
区间查询最值
1 | int query(int c,int l,int r,int x,int y){ |
树上查询
(这是在树上查询,树剖的大作用就是这个,会详解)
1 | int ask(int x,int y){ |
还有两个树上修改
大家结合上面的修改看看吧(这不是我偷懒!!)
1 | void DO1(int x,int y,int k){//树上加边权 |
就是以上的几种操作,是不是好简单呢!!
当然,为什么我没写树剖要的那两个DFS呢,因为之前有写过了
谢谢大家的阅读!!!!!!!!!!!!!!!!!!!!!
下面给出完整代码:
完整代码
(码风就不要在意了)
1 |
|
小结
这一题不难,就是一道树剖模板。