演算法討論 樹鏈剖分 學習筆記

2021-08-01 03:47:58 字數 1853 閱讀 9224

模板及講解

樹鏈剖分解決樹上的修改問題。

將樹剖成一條條鏈,再用線段樹、樹狀陣列等維護

常見題型:

1.點權問題

q:修改某些點的權進行詢問。

解:直接樹剖進行線段樹/樹狀陣列維護

例題:bzoj1036

2.邊權問題

q:修改某些邊的權進行詢問。

解:樹剖後維護點權,每個點的點權為這個點到他父親之間邊權,詢問時刪除lca的點權即可

例題:poj2763

3.子樹問題

#include

#include

#include

#include

#define fo(i, j, k) for (i=(j);i<=(k);i++)

#define fd(i, k, j) for (i=(k);i>=(j);i--)

#define rd(a) scanf("%d", &a)

#define rd2(a, b) scanf("%d%d", &a, &b)

#define rd3(a, b, c) scanf("%d%d%d", &a, &b, &c)

#define ms(i, j) memset(i, j, sizeof i)

#define fn2 "bzoj1036"

using

namespace

std;

const

int maxn = 30000 + 5;

int dep[maxn], son[maxn], fa[maxn], siz[maxn]; //深度,重兒子,父親,子樹大小

int n, wi[maxn];

vector

g[maxn];

void dfs1(int u, int f)//第一次dfs記錄值

}}int maxv[maxn*4], sumv[maxn*4];

void pushup(int o)

void update(int o, int l, int r, int p, int v)

if (p<=m) update(lc, l, m, p, v); else

if (m1, r, p, v);

pushup(o);

}int getmax(int o, int l, int r, int x, int y)

if (x<=m) ret = max(ret, getmax(lc, l, m, x, y));

if (m1, r, x, y));

return ret;

}int getsum(int o, int l, int r, int x, int y)

if (x<=m) ret += getsum(lc, l, m, x, y);

if (m1, r, x, y);

return ret;

}int findmax(int u, int v)

if (dep[u]return max(ret, getmax(1, 1, n, p[v], p[u]));

}int findsum(int u, int v)

if (dep[u]return ret+getsum(1, 1, n, p[v], p[u]);

}void init()

}void solve() else

if (ch[1]=='m') else

if (ch[1]=='s')

}}int main()

樹鏈剖分學習筆記

寫 又犯了很sb的錯誤,線段樹寫錯了。好像每次都會把r l 1寫成l r 1,然後就只有20分。寫的比較醜,壓了壓之後190行。基本上是我打過的最長的乙個模板了 然後簡單介紹一下樹剖吧。樹鏈剖分,就是把樹剖分成鏈,然後用資料結構來維護這些鏈,使得詢問 修改的複雜度達到o logn o l ogn 不...

樹鏈剖分學習筆記

樹鏈剖分 mod estc oder modestcoder modest code r如果你是重兒子,你就在重路徑上。如果你是輕兒子,暴力沿著祖先向上爬最多log nlogn logn 次就可以遇到重路徑。或者到根 而樹上操作基本就是找祖先 也許有人喜歡我的碼風 include include d...

樹鏈剖分學習筆記

前言 書上只講了重鏈剖分,菜雞也只會這一種,想看其他的是別想了。要會樹鏈剖分,首先你需要了解一些概念。我們把乙個節點的所有兒子節點中子樹節點數最大的稱為重兒子,也就是size最大的子節點。size的定義我在講換根dp時說過,因此不再贅述。對於每個節點的重兒子,我們用 son x 來記錄它,父親節點到...