bzoj 4034 DFS序 線段樹

2022-05-18 06:01:05 字數 1912 閱讀 3423

這個題多了乙個操作難度直線上公升,看完題解才會寫

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

操作,分為三種:

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

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

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

按照題意:記錄其dfs序,然後進棧是正,出棧為負,利用線段樹進行更新

#include #include 

#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;const

int n = 800005

;struct

edge

edge[n

<<1

];int

head[n],tot,cnt;

intval[n];

intin[n],out

[n];

ll tree[n

<<2],lazy[n<<2

],seg[n];

int flag[n<<2

];int

io[n];

void addedge(int u,int

v)void

init()

void dfs(int u,int

fa) }

seg[

out[u] = ++cnt] = (ll)(-val[u]);

io[cnt] = -1;}

void pushup(int

idx)

void pushdown(int

idx)

return;}

void build(int l,int r,int

idx)

int mid = (l+r)>>1

; build(l,mid,idx

<<1

); build(mid+1,r,idx<<1|1

); pushup(idx);

flag[idx] = flag[idx<<1] + flag[idx<<1|1];}

void update(int l,int r,int l,int r,int idx,int

val)

int mid = (l+r)>>1

; pushdown(idx);

if(mid>=l) update(l,mid,l,r,idx<<1

,val);

if(mid1,r,l,r,idx<<1|1

,val);

pushup(idx);

}ll query(

int l,int r,int l,int r,int

idx)

int mid = (l+r)>>1

; ll sum = 0

; pushdown(idx);

if(mid>=l) sum+=query(l,mid,l,r,idx<<1

);

if(mid1,r,l,r,idx<<1|1

);

return

sum;

}int

main()

for(int i=1; i)

dfs(

1,0);

build(

1,2*n,1

);

while(m--)

else

if(op==2

)else}}

}

BZOJ 4034 線段樹 DFS序

思路 先搞出來每個點的dfs序 要有入棧和出棧兩種狀態的 處理出來 線段樹區間有多少入棧的和多少出棧的 加區間的時候就加 入 出 wei 查字首和 by siriusren include include include using namespace std define n 200050 def...

dfs序 線段樹

傳送門 現有一棵樹,有以下操作 1.節點x及其所有子孫顏色都變更為k。2.要求你回答節點x的顏色。初始所有點都沒有染色。input 第一行乙個整數t t 10 表示樣例組數。對於每個測試樣例 第一行乙個整數n n 5e4 表示樹的節點個數。接下來n行,每行兩個整數u,v 1 u,v n 表示樹中u的...

BZOJ 3252攻略 dfs序 線段樹

bzoj 3252 攻略 dfs序 線段樹 題目大意 給定一棵以1為根的n個點的樹,樹有點權且點權為正整數,可以選擇k條以根作為起點的路徑,每條路徑的價值即這條路徑上所有點的點權之和。但是選擇一條路徑之後,這條路徑上的所有點的點權會變成0。也就是說,這k條路徑中被重複選擇的點,其點權只能被計算一次 ...