BZOJ4034 HAOI2015 樹上操作

2021-08-07 22:44:02 字數 1688 閱讀 5137

有一棵點數為 n 的樹,以點 1 為根,且樹點有邊權。然後有 m 個

操作,分為三種:

操作 1 :把某個節點 x 的點權增加 a 。

操作 2 :把某個節點 x 為根的子樹中所有點的點權都增加 a 。

操作 3 :詢問某個節點 x 到根的路徑中所有點的點權和。

第一行包含兩個整數 n, m 。表示點數和運算元。接下來一行 n 個整數,表示樹中節點的初始權值。接下來 n-1 

行每行三個正整數 fr, to , 表示該樹中存在一條邊 (fr, to) 。再接下來 m 行,每行分別表示一次操作。其中

第乙個數表示該操作的種類( 1-3 ) ,之後接這個操作的引數( x 或者 x a ) 。

對於每個詢問操作,輸出該詢問的答案。答案之間用換行隔開。

5 51 2 3 4 5

1 21 4

2 32 5

3 31 2 1

3 52 1 2

3 369

13題解

又是一道裸的樹鏈剖分。

這裡有乙個新的操作,子樹加。我們發現子樹是一段連續的區間,所以在dfs2是標記一下右端點就行了。

#include#include#include#include#define ll long long

using namespace std;

const int maxn=200010;

int pre[maxn],last[maxn],other[maxn],num,dfs[maxn],top[maxn],dep[maxn];

int r[maxn],sz[maxn],fa[maxn],son[maxn],n,m,belong[maxn];

int cnt;

ll w[maxn];

struct treet[maxn*4];

void add(int x,int y)

void dfs1(int x)

void update(int x)

t[x*2].sum+=(ll)(t[x*2].r-t[x*2].l+1)*t[x].lazy;

t[x*2].lazy+=t[x].lazy;

t[x*2+1].sum+=(ll)(t[x*2+1].r-t[x*2+1].l+1)*t[x].lazy;

t[x*2+1].lazy+=t[x].lazy;

t[x].lazy=0;

}void change(int x,int l,int r,long long k)

if(t[x].lazy)

update(x);

change(x*2,l,r,k);

change(x*2+1,l,r,k);

t[x].sum=t[x*2].sum+t[x*2+1].sum;

}ll query(int x,int l,int r)

if(t[x].lazy)

update(x);

return query(x*2,l,r)+query(x*2+1,l,r);

}ll work(int l,int r)

int main(){

int x,type;long long y;

scanf("%d%d",&n,&m);

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

scanf("%lld",&w[i]);

for(int i=1;i

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 表示點數和運算元。接下來一...