bzoj4034 HAOI2015 樹上操作

2022-04-30 04:36:13 字數 1600 閱讀 9776

這題其實就是樹剖裸題啊。

然後毒瘤選手由於上題樹剖被卡到哭所以選擇dfs序+樹狀陣列。

不得不說簡單的演算法做出來更加難思考。然後網上的dalao們都一筆帶過淨說什麼用兩個樹狀陣列維護就可以啦。

經過大半小時的思考,**實現還是非常簡單。

這個值得詳細講講。

假如我們弄乙個樹狀陣列,然後維護的是x到根的sum(其實就是詢問的答案嘛),先看第乙個操作,單點修改,那麼改了這個點,相當於把他這一整棵子樹的答案都加上了d,由於用dfs序重新編號,可以發現子樹中的點都是連續的,那麼樹狀陣列改段求段就可以用差分陣列解決。

問題在於第二個操作,修改了整個子樹,對每個節點y的影響是d*(dep[x]-dep[y]),那麼非常難受,因為每個點改變的值和dep有關,並不相同,怎麼辦?絕佳的方法就是我們忽略dep的影響,用另乙個樹狀陣列維護d,那麼問題又來了,x肯定不是時時相同的,雖然詢問y的時候可以知道dep[y],但是dep[x]仍然不確定,為了可以確定,那麼對於每次這種修改,我們就在第乙個樹狀陣列給它減去d*(dep[x]-1),這樣一來,就把這個操作轉化成增加x整個子樹和x到根的路徑上的點,那麼對於每個點,增加的數就變成d*dep[y],那麼求解的時候,就可以心安理得的用第乙個樹狀陣列的值+第二個樹狀陣列的值*d了。

#include#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;int

n,m;

struct

node

a[210000];int len,last[110000

];void ins(int x,int

y)int z,dep[110000],l[110000],r[110000

];void dfs(int x,int

f) r[x]=z;}//

---------init-----------------

ll s[

2][110000

];int lowbit(int x)

void change(int w,int

x,ll k)

}ll getsum(

int w,int

x)

return

ret;}//

-----------bit--------------

ll point[

110000

];int

main()

z=0;dep[1]=1;dfs(1,0

);

//init

for(int i=1;i<=n;i++)

change(

0,l[i],point[i]), change(0,r[i]+1,-point[i]);

intop;ll d;

for(int i=1;i<=m;i++)

else

if(op==2

)

else

}return0;

}

bzoj4034 HAOI2015 樹上操作

傳送門 description 有一棵點數為 n 的樹,以點 1 為根,且樹點有邊權。然後有 m 個 操作,分為三種 操作 1 把某個節點 x 的點權增加 a 操作 2 把某個節點 x 為根的子樹中所有點的點權都增加 a 操作 3 詢問某個節點 x 到根的路徑中所有點的點權和。input 第一行包含...

bzoj 4034 HAOI2015 樹上操作

4034 haoi2015 樹上操作 time limit 10 sec memory limit 256 mb submit 4216 solved 1340 submit status discuss description 有一棵點數為 n 的樹,以點 1 為根,且樹點有邊權。然後有 m 個 ...

BZOJ 4034 HAOI2015 樹上操作

有一棵點數為 n 的樹,以點 1 為根,且樹點有邊權。然後有 m 個 操作,分為三種 操作 1 把某個節點 x 的點權增加 a 操作 2 把某個節點 x 為根的子樹中所有點的點權都增加 a 操作 3 詢問某個節點 x 到根的路徑中所有點的點權和。第一行包含兩個整數 n,m 表示點數和運算元。接下來一...