HDU5044 Tree 樹鏈剖分

2022-05-23 18:36:07 字數 1929 閱讀 7438

大致題意:add1 u v   u到v路徑上所有點的權值加上k,add2  u 到v路徑上所有邊的權值加上k

最後輸出所有點的權值,邊的權值。。樹鏈剖分預處理然後來個線性o(n)的操作。剛開始用線段樹tle了.

1

#pragma comment(linker, "/stack:1024000000,1024000000")

2 #include 3 #include 4 #include 5 #include 6 #include 7

using

namespace

std;

8 typedef unsigned long

long

ull;

9 typedef long

long

ll;10

const

int inf = 0x3f3f3f3f;11

const

int maxn = 1e5+10;12

struct

13 e[maxn<<1

];16

inthead[maxn],edge;

17void add(int x,int

y)18

2324

intson[maxn],fa[maxn],siz[maxn],dep[maxn];

25void dfs1(int

root)

2640}41

}42inttop[maxn],pos[maxn],fp[maxn],tot;

43void dfs2(int root,int

f)44

54 ll addv[3][maxn<<2

];55

intk;

56void pre_update(int ua,int ub,int

cho)

5769

if (dep[ua] >dep[ub])

70swap(ua,ub);

71if (cho == 1

)72 addv[cho][pos[ua]] += k,addv[cho][pos[ub]+1] -=k;

73if (cho == 2

)74 addv[cho][pos[son[ua]]] += k,addv[cho][pos[ub]+1] -=k;75}

76int n,m,d[maxn][2

],link[maxn];

77void

init()

7894

dfs1(root);

95dfs2(root,root);

96for (int i = 1; i < n; i++)

97102

}103

ll ans1[maxn],ans2[maxn];

104int main(void

)105

120for (int i = 1; i <= n; i++)

121127 printf("

case #%d:\n

",cas++);

128 printf("

%i64d

",ans1[1

]);129

for (int i = 2; i <= n; i++)

130133 printf("\n"

);134

if (n>1

)135 printf("

%i64d

",ans2[1

]);136

for (int i = 2; i < n; i++)

137140 printf("\n"

);141

}142

return0;

143 }

view code

HDU 5044 Tree 樹鏈剖分

題意 給一棵樹,兩種操作 add1 給u v路徑上所有點加上值k,add2 給u v路徑上所有邊加上k,初始值都為0,問最後每個點和每條邊的值,輸出。解法 樹鏈剖分可做,剖出來如果直接用線段樹來區間更新的話會tle,所以要換一種姿勢,有一種樹鏈剖分的經典姿勢就是看做樹狀陣列一樣,每次加值的時候,比如...

HDU 5044 Tree (樹鏈剖分)

這題用線段樹貌似過不了,和nyoj 的士兵殺敵五一樣,經過樹鏈剖分後,就把樹剖分成許多鏈,這樣可以對整個鏈操作,結合字首和的思想,如果某個節點到祖先節點更新這間的所有節點,可以把祖先節點 k 讓當前節點編號 1 減 k 這樣最後跑一邊陣列就可以了,葉子節點的時候類似。pragma comment l...

poj3237 Tree 樹鏈剖分

這個題是spoj的改版 是在原來的題意上增加了區間取反操作 所以只需要在spoj375的基礎上再線段樹上增加乙個取反標誌 同時在維護乙個區間最小值 因為在區間取反了以後 區間的最大值就是區間原來的最小值 嗯 就這樣就可以了 include include include using namespac...