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<=106,1<=R<=N,106<=x,vi<=1061<=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

【題意】

給定一棵n個點的樹,要求支持以下操作:

  1. 把樹上鍊(a,b)的權值加上x
  2. 詢問點a的權值
  3. 詢問點a的子樹的權值和

【思路】

首先我們來看修改操作,dfs序最基礎的修改就是單點修改權值,但是這邊是區間修改,很容易想到樹狀數組的區間更新,單點查詢,更新的時候利用差分。

但是由於是是樹鏈,無法直接映射到一個完整的區間,所以這個時候需要畫個圖。

類比於求兩點之間距離,我們跟根去找關係,可以發現,樹鏈上加x,相當於從根到a,從根到b的路徑上都加上x,但是這樣會有重複,他們的lca多算了一遍,再往上多算了兩遍,減掉即可。

還有值得注意的是,這邊顯而易見我們需要維護的是葉子節點到某一個點的差分值,即從下往上差分(設點i上儲存的差分值爲valival_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]的值即可。

【注】這道題比較卡時間,加了讀入掛才能過

我是代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章