HAOI2015 樹上操作 DFS序 線段樹

2021-08-21 22:29:03 字數 2131 閱讀 1143

題目大意:給定一棵樹,每個點有點權。有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 ...