LOJ146 DFS 序3,树上差分1【DFS】

DFS 序3,树上差分1
Time Limit: 2000 MS Memory Limit: 131072 K

Problem Description

这是一道模板题。
给一棵有根树,这棵树由编号为1…N的N个结点组成。根结点的编号为 R。每个结点都有一个权值,结点i的权值为vi。 接下来有M组操作,操作分为两类:

  1. 1 a b x,表示将「结点a到结点b的简单路径」上所有结点的权值都增加x;
  2. 2 a,表示求结点a的权值。
  3. 3 a,表示求a的子树上所有结点的权值之和。

Input

第一行有三个整数N,M和R。
第二行有N个整数,第i个整数表示vi。
在接下来的N-1行中,每行两个整数,表示一条边。
在接下来的M行中,每行一组操作。
1 < = N , M < = 1 0 6 , 1 < = R < = N , 1 0 6 < = x , v i < = 1 0 6 1<=N,M<=10^6,1<=R<=N,-10^6<=x,v_i<=10^6

Output

针对询问,输出相应的答案

Examples

Input
10 17 3
5 1 -7 -9 -5 3 -7 -5 3 3
1 8
8 7
7 6
8 3
6 10
7 2
6 9
1 4
6 5
2 9
1 10 4 -2
2 8
1 1 10 -2
3 5
1 10 6 -3
3 1
1 6 5 9
2 8
1 4 5 1
2 10
1 2 5 6
1 2 6 0
1 2 7 -5
1 4 9 6
1 10 1 0
3 2

Output
3
-7
-5
-10
-9
-4
2

【题目链接】 DFS 序3,树上差分1

【题意】

扫描二维码关注公众号,回复: 9888557 查看本文章

给定一棵n个点的树,要求支持以下操作:

  1. 把树上链(a,b)的权值加上x
  2. 询问点a的权值
  3. 询问点a的子树的权值和

【思路】

首先我们来看修改操作,dfs序最基础的修改就是单点修改权值,但是这边是区间修改,很容易想到树状数组的区间更新,单点查询,更新的时候利用差分。

但是由于是是树链,无法直接映射到一个完整的区间,所以这个时候需要画个图。

类比于求两点之间距离,我们跟根去找关系,可以发现,树链上加x,相当于从根到a,从根到b的路径上都加上x,但是这样会有重复,他们的lca多算了一遍,再往上多算了两遍,减掉即可。

还有值得注意的是,这边显而易见我们需要维护的是叶子节点到某一个点的差分值,即从下往上差分(设点i上储存的差分值为 v a l i val_i )。

完成了更新操作之后,第二个询问就迎刃而解了,query(ri[x])-query(le[x]-1),算出来的就是x的所有子树的差分值总和,这些值都作用于点x,即为答案。

对于询问三,我们去寻求x的子树上的点v对x的子树和的贡献,为val[v]*(dep[v]-dep[x]+1),后面的乘数即为点v的差分值在这颗子树中作用到的点。其中dep[x]固定,val[v]可以求解,所以把式子拆成val[v]*dep[v] - val[v] * (dep[x]-1),后者因为可以同2求得val[v]的总和,所以可以直接计算,前者我们只要再用一个树状数组维护val[v]*dep[v]的值即可。

【注】这道题比较卡时间,加了读入挂才能过

我是代码

发布了259 篇原创文章 · 获赞 100 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/my_sunshine26/article/details/93968415
dfs