樹鏈剖分其實就是把一棵樹剖分成一條條鏈(重鏈輕鏈),然後用線段樹進行操作維護。複雜度logn
記錄 deep[ ] size[ ] fa[ ] pos[ ] bl[ ]陣列
deep深度,size子樹節點個數,pos節點編號,bl所在重鏈頂端節點編號,fa父親編號。
例題:bzoj1036
#include
#define inf 1234567890;
#define n 30005
#define m 60005
using namespace std;
int n,q,sz,id;
int v[n],deep[n],size[n],head[n],fa[n];
int pos[n],bl[n];
struct datae[m];
struct segt[100005];
int read()
//讀入
void add(int u,int v) //加邊
void init()
if (k==0) return;//若沒有退出
dfs2(k,chain);//以重兒子為基礎繼續拓展
for (int i=head[u];i;i=e[i].next)
}//dfs2求出bl pos
void build(int k,int l,int r)
//構造線段樹
int max(int a,int b)
void change(int k,int x,int y)
if (x<=mid) change(k<<1,x,y);
else change(k<<1|1,x,y);
t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx);
}//線段樹單點修改
int qsm(int k,int x,int y)
//線段樹求和
int qmx(int k,int x,int y)
//線段樹最大值
void swap(int &a,int &b)
int ssm(int x,int y)
int smx(int x,int y)
void solve()
else }}
int main()
樹鏈剖分學習
樹鏈剖分 看了學習了樹鏈剖分 適用於在樹上的路徑操作。關鍵在於重鏈的構造,把它表示到了資料結構上的連續區間,降低了複雜度。主要操作步驟實際上有三個部分 1 構造重鏈 2 如何維護資料 3 分解為輕重鏈的查詢與修改 include include include include define n 10...
樹鏈剖分學習
之前寫過樹剖的題,但沒有完全理解,現在又無法複述思路了,所以重新學習一下,部分語句參考大神的敘述 一 概念 樹鏈剖分,顧名思義,樹是由一根根樹鏈組成的,我們現在要來把它按鏈來分解掉。我們知道,大部分樹上的問題都是圍繞樹的路徑來做文章,分解成一條條的鏈之後,我們就可以對節點 邊 就行編號了,而同一根鏈...
樹鏈剖分學習
兩次dfs,第一次處理處fa,depth,size,son,第二次處理出top,rank,id 一條重鏈的編號是連續的,可以用資料結構維護,做事情的時候判斷是否在同一條鏈上,不是就把最深的跳到鏈頭的fa,然後繼續判斷 luogu3384 模板 樹鏈剖分 區間加,求和,子樹加,求和 include i...