做法**
more
有一棵點數為 n 的樹,以點 1 為根,且樹點有邊權。然後有 m 個操作,分為三種:
操作 1 :把某個節點 x 的點權增加 a 。
操作 2 :把某個節點 x 為根的子樹中所有點的點權都增加 a 。
操作 3 :詢問某個節點 x 到根的路徑中所有點的點權和。
傳送門
鏈式前向星加邊
兩次dfs,第一次算出父節點,子樹大小,深度,重兒子,第二次算出每個點的dfs序號,每一條鏈的鏈首
建線段樹
樹鏈剖分
#include
#include
using
namespace std;
typedef
long
long ll;
const
int n =
1e5+10;
const
int inf =
0x3f3f3f3f
;int n, m, tot =
0, cnt =0;
int head[n]
;//父節點,子樹大小,重兒子,深度
int anc[n]
, size[n]
, son[n]
, dep[n]
;//鏈首, dfs的時間戳以及它的反函式
int top[n]
, dfn[n]
, pre[n]
;//點權
ll w[n]
;struct edgee[n <<1]
;inline
void
add(
int u,
int v)
; head[u]
= tot;
}void
dfs1
(int u,
int fa)
}void
dfs2
(int u,
int tp)
}//線段樹
//支援單點更新,區間更新,區間查詢
struct tree
}t[n <<2]
;inline
void
push_up
(int i)
inline
void
buildtree
(int i,
int l,
int r)
int mid = t[i]
.mid()
;buildtree
(i <<
1, l, mid)
;buildtree
(i <<1|
1, mid +
1, r)
;push_up
(i);
}inline
void
push_down
(int i)
inline
void
add_point
(int i,
int x, ll val)
if(t[i]
.la)
;push_down
(i);
int mid = t[i]
.mid()
;if(x <= mid)
add_point
(i <<
1, x, val)
;else
add_point
(i <<1|
1, x, val)
;push_up
(i);
}inline
void
add_interval
(int i,
int l,
int r, ll val)
if(t[i]
.la)
push_down
(i);
int mid = t[i]
.mid()
;if(l <= mid)
add_interval
(i <<
1, l, r, val);if
(r > mid)
add_interval
(i <<1|
1, l, r, val)
;push_up
(i);
}ll query_interval
(int i,
int l,
int r)
push_down
(i);
ll res =0;
int mid = t[i]
.mid()
;if(l <= mid)
res +
=query_interval
(i <<
1, l, r);if
(r > mid)
res +
=query_interval
(i <<1|
1, l, r)
;return res;
}//子樹點權和的詢問
ll tree_sum
(int u,
int v)
ans +
=query_interval(1
, dfn[top[u]
], dfn[u]);
u = anc[top[u]];
}if(dfn[u]
> dfn[v]
)swap
(u, v)
; ans +
=query_interval(1
,dfn[u]
, dfn[v]);
return ans;
}inline
void
solve()
else
if(op ==2)
else
if(op ==3)
}int
main()
dfs1(1
,-1)
;dfs2(1
,1);
buildtree(1
,1, n)
;while
(m--
)solve()
;return0;
}
樹剖2
樹剖3樹剖4
洛谷 3178 樹上操作
作為乙個比樹剖板子還板子的題目,它竟讓我卡了近乙個下午。出去不敢說自己是學過樹剖的人。對於這道題目,會樹剖的都會做 不會別說會樹剖 其主要任務是用樹剖維護區間和,支援區間 單點修改。我的 這次主要就是卡在這裡了。首先我們要明確每個變數陣列的意義,並且明確他們下表的意義。int siz 102020 ...
洛谷 3178 樹上操作
有一棵點數為 n 的樹,以點 1 為根,且樹點有邊權。然後有 m 個操作,分為三種 輸入格式 第一行包含兩個整數 n,m 表示點數和運算元。接下來一行 n 個整數,表示樹中節點的初始權值。接下來 n 1 行每行兩個正整數 from,to 表示該樹中存在一條邊 from,to 再接下來 m 行,每行分...
洛谷P3178 HAOI2015 樹上操作
有一棵點數為 n 的樹,以點 1 為根,且樹點有邊權。然後有 m 個操作,分為三種 操作 1 把某個節點 x 的點權增加 a 操作 2 把某個節點 x 為根的子樹中所有點的點權都增加 a 操作 3 詢問某個節點 x 到根的路徑中所有點的點權和。輸入格式 第一行包含兩個整數 n,m 表示點數和運算元。...