題目大意:給定一棵樹,每個點有點權。有m個操作:
定睛一看,這不就是樹鏈剖分的模板題嗎?!連問題都是一樣的。。。(樹鏈剖分模板)不過因為我寫的不熟,只能大力線段樹。。。
思路:首先把樹的dfs序求出來,這樣就把樹上的操作轉化為區間操作,再記錄一下進棧出棧順序。隨後構建線段樹,每段區間記錄進棧點和出棧點個數。
操作1:進棧點,出棧點修改。
操作2:找到這個點的進棧,出棧,再區間加。
操作3:直接求根到進棧點的字首和。
#include
#include
#include
using
namespace std;
const
int maxn =
100001
;int w[maxn]
;int begin[maxn]
, end[maxn]
;int fir[maxn]
, nxt[maxn <<1]
, to[maxn <<1]
, cnt;
int a[maxn <<1]
, cur, flag[maxn <<1]
;struct nodet[maxn <<3]
;inline
intread()
while
(ch >=
'0'&& ch <=
'9')
return k * f;
}inline
void
add_edge
(int a,
int b)
inline
void
pushup
(int u)
inline
void
add(
int u,
long
long k)
inline
void
pushdown
(int u)
}void
build
(int u,
int l,
int r)
int mid =
(l + r)
>>1;
build
(u <<
1, l, mid)
;build
(u <<1|
1, mid +
1, r)
; t[u]
.num[0]
= t[u <<1]
.num[0]
+ t[u <<1|
1].num[0]
; t[u]
.num[1]
= t[u <<1]
.num[1]
+ t[u <<1|
1].num[1]
;pushup
(u);
}void
change
(int u,
int l,
int r,
long
long k)
pushdown
(u);
if(t[u <<1]
.r >= l)
change
(u <<
1, l, r, k);if
(t[u <<1|
1].l <= r)
change
(u <<1|
1, l, r, k)
;pushup
(u);
}long
long
query
(int u,
int l,
int r)
void
dfs(
int u,
int fa)
a[++cur]
= u;
flag[cur]=0
; end[u]
= cur;
}int
main()
dfs(1,
0);build(1
,1, cur)
;for
(int i =
1; i <= m; i++)}
return0;
}
鴿了幾天了,咕咕咕~ HAOI2015 樹上操作
題目描述 有一棵點數為 n 的樹,以點 1 為根,且樹點有邊權。然後有 m 個操作,分為三種 操作 1 把某個節點 x 的點權增加 a 操作 2 把某個節點 x 為根的子樹中所有點的點權都增加 a 操作 3 詢問某個節點 x 到根的路徑中所有點的點權和。輸入格式 第一行包含兩個整數 n,m 表示點數...
HAOI2015 樹上操作
有一棵點數為 n 的樹,以點 1 為根,且樹點有邊權。然後有 m 個操作,分為三種 操作 1 把某個節點 x 的點權增加 a 操作 2 把某個節點 x 為根的子樹中所有點的點權都增加 a 操作 3 詢問某個節點 x 到根的路徑中所有點的點權和。輸入格式 第一行包含兩個整數 n,m 表示點數和運算元。...
HAOI2015 樹上操作
嘟嘟嘟 樹剖自然可解,就是一道板子題,而且這道題還只問到根節點的距離是多少,而不是樹上任意兩點距離,就更方便了。1 include2 include3 include4 include5 include6 include7 include8 include9 include10 include11 ...