建議學樹剖的同學先學會dfs序,並有一定的資料結構基礎
樹鏈剖分,計算機術語,指一種對樹進行劃分的演算法,它先通過輕重邊剖分將樹分為多條鏈,保證每個點屬於且只屬於一條鏈,然後再通過資料結構(樹狀陣列、sbt、splay、線段樹等)來維護每一條鏈。
那它有什麼用呢?
它可以解決一些樹上路徑的一些問題。
一般的樹剖是輕重鏈剖分。當然還有更高階的長鏈剖分等。這裡先講輕重鏈剖分。
sz[x]:以x為根的子樹的節點個數
to[x]:x中節點最多的兒子編號(重兒子)
重邊:連線x與to[x]的邊
輕邊:除了重邊以外的邊
重鏈:由重邊構成的鏈
輕鏈:除了重邊以外的鏈
tp[x]:x所在的重鏈的起始點
剖分完後有一些性質:
輕邊(u,v),size(v)<=size(u)/2。 ž從根到某一點的路徑上,不超過o(logn)條輕邊,不超過o(logn)條重路徑。
容易發現樹剖是啟發式的。
實現輕重鏈剖分我們可以用兩遍dfs實現
第一遍dfs:求出每個節點的父親、深度、sz、to等。這個比較簡單。
void dfs1(int x,int depth)
}
第二遍dfs:優先遍歷重兒子。對於每乙個重兒子,繼承當前節點的重鏈。對於其它兒子,重新拉一條以自己為端點的重鏈。
void dfs2(int x)
仔細體會一下就可以發現,輕重鏈剖分其實就是優先遍歷重兒子的乙個dfs序。每一條重鏈/每乙個子樹都是連續的一段區間。
對於x到y的一條路徑,可以把它劃分為若干條重鏈(當然最後一條可能不完整)。
假設tp[x]>=tp[y]。
當tp[x]!=tp[y]時,對x到tp[x]這一段進行操作,然後把x賦成fa[tp[x]],重複上述操作。
當tp[x]=tp[y]時,對x到y這一段進行操作,結束操作。
下面給出偽**:
各種型別 函式名稱(int x,int y)
if (dep[x]id[y]到id[x])
}
以bzoj1036(洛谷p2590)為例:
這道題的操作有單點修改和詢問路徑最大值及路徑點權和,所以我們可以用線段樹維護。
**:
#include
#include
#include
#include
#define n 30005
using namespace std;
struct treet[n*4];
struct edgeed[n*2];
int n,m,k,nd,a[n],fa[n],dep[n],tp[n],to[n],h[n],sz[n],id[n],in[n];
inline int _read()
while (isdigit(ch)) num=(num<<3)+(num<<1)+(ch^48),ch=getchar();
return num*f;
}void addedge(int x,int y)
void dfs1(int x,int depth)
}void dfs2(int x)
void build(int l,int r,int x)
int mid=l+r>>1; build(l,mid,x*2),build(mid+1,r,x*2+1);
t[x].sum=t[x*2].sum+t[x*2+1].sum;
t[x].mx=max(t[x*2].mx,t[x*2+1].mx);
}void mdfy(int x,int p,int w)
int mid=t[x].l+t[x].r>>1;
if (p<=mid) mdfy(x*2,p,w);
else mdfy(x*2+1,p,w);
t[x].sum=t[x*2].sum+t[x*2+1].sum;
t[x].mx=max(t[x*2].mx,t[x*2+1].mx);
}tree find(int x,int l,int r)
tree srch(int x,int y)
if (dep[x]1,id[y],id[x]);
ans.mx=max(ans.mx,ret.mx);
ans.sum+=ret.sum; return ans;
}int main()
for (int i=1;i<=n;i++) a[i]=_read();
dfs1(1,1),tp[1]=1,dfs2(1),build(1,n,1);
m=_read(); char s[10]; int x,y;
while (m--)
}return
0;}
bzoj1036 樹的統計 樹鏈剖分 LCT
ac通道 題解 看到題目,發現是樹剖一眼題,所以就秒掉了。include include include include include include includeusing namespace std typedef long long ll define file read define m...
BZOJ 1036 樹的統計 樹鏈剖分模板
樹上n個點,支援單點修改,區間查詢最大值和sum和。此處只講大體思路,樹鏈剖分的詳細原理請移步op x top x top x 即該點的 dfs dfsdf s區間修改和區間查詢,就是先處理出兩點之間的樹鏈,由於樹鏈上的點的 dfs dfsdf s下面的 包括了區間修改和單點修改,以及區間查詢最大值...
BZOJ 1036 樹的統計 Count 樹鏈剖分
題目大意 一棵樹上有n個節點,編號分別為1到n,每個節點都有乙個權值w。我們將以下面的形式來要求你對這棵樹完成一些操作 i.change u t 把結點u的權值改為t ii.qmax u v 詢問從點u到點v的路徑上的節點的最大權值 iii.qsum u v 詢問從點u到點v的路徑上的節點的權值和 ...