這個題多了乙個操作難度直線上公升,看完題解才會寫
有一棵點數為 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條路徑中被重複選擇的點,其點權只能被計算一次 ...