模板總結 樹鏈剖分

2021-08-20 04:20:26 字數 2501 閱讀 5748

給定一顆樹,要求對樹上的路徑(u,v)進行高效操作。

(1)更新路徑(u,v)上所有點的權值,單點查詢樹上某點的權值

(2)更新結點u的權值,查詢路徑(u,v)上的權值和

(3)更新路徑(u,v)上的權值,查詢路徑(u,v)上的權值和

(4)更新結點u的權值,查詢路徑(u,v)上的lcis

(5)更新結點u到根結點路徑上的權值,更新u子樹的權值,查詢u到根結點權值,查詢u子樹權值

樹鏈剖分就是將樹上的結點重新編乙個號,形成乙個連續的區間,通過維護這個區間從而達到維護樹的目的。

因為樹鏈剖分多是對路徑的操作,所以這個重新編號工作要使得乙個路徑可以切分成幾個連續區間。

所以引入重鏈的概念,要求每一條重鏈上的結點都是連續的,每乙個子樹上的結點都是連續的。

重兒子:u的重兒子是v當且僅當v子樹的結點總數(包括v)是u的所有子樹中結點總數最大的

輕兒子:每個非葉子結點只有乙個重兒子,其他是輕兒子

重鏈:由重兒子向父結點連重邊,一段最長連續重邊叫做重鏈

主要目的是確定重兒子。

要確定重兒子son,需要確定子樹結點總數sz.

確定深度dep和父結點fa是因為對路徑操作需要。

void dfs1(int u,int f,int deep)//第一遍dfs確定結點深度dep和重兒子son以及為了確定重兒子而所需要知道的資訊sz

}}

主要目的是將樹的結點與區間的點對應起來。

每條重鏈是乙個連續區間,所以需要確定重鏈。

確定重鏈的頂端結點top是因為對路徑操作需要,一爬爬一條路徑,速度快。

通過兩次dfs就成功地將樹與一段區間對應起來了,接下來用樹狀陣列或線段樹去維護區間即可。

void dfs2(int u,int topf)//第二遍dfs按重兒子走,確定每一條樹鏈

}

對路徑的查詢與更新操作類似。

void update_path(int x,int y,int k)//將路徑x-y上的所有結點的值都加k

//直到兩個點在一條鏈上

if(dep[x]>dep[y]) swap(x,y);//將x改為本身深度更淺的結點

//更新路徑x-->y

//結點x和y對應在樹狀陣列中的結點編號

int l=id[x],r=id[y];

add(l,k);

add(r+1,-k);

}

//hdu3966

#include

#include

#include

#include

#include

using

namespace

std;

const

int maxn=5e4+100;

//樹狀陣列

int tree[maxn],a[maxn];

int lowbit(int i)

void add(int i,int v)

return ans;

}//樹鏈剖分

vector

g[maxn];//存圖

int cnt;//樹狀陣列中的元素的編號

int dep[maxn];//在樹中的深度

int id[maxn];//id[u]表示u結點對應在樹狀陣列中的編號

int pos[maxn];//pos[i]表示樹狀陣列第i個元素對應的樹中結點

int top[maxn];//該結點所在鏈的頂端的結點

int son[maxn];//該結點的重兒子

int sz[maxn];//以該結點為根的樹所含結點總數

int fa[maxn];//該結點的父結點

void dfs1(int u,int f,int deep)//第一遍dfs確定結點深度dep和重兒子son以及為了確定重兒子而所需要知道的資訊sz

}}void dfs2(int u,int topf)//第二遍dfs按重兒子走,確定每一條樹鏈

}void update_path(int x,int y,int k)//將路徑x-y上的所有結點的值都加k

//直到兩個點在一條鏈上

if(dep[x]>dep[y]) swap(x,y);//將x改為本身深度更淺的結點

//結點x和y對應在樹狀陣列中的結點編號

int l=id[x],r=id[y];

add(l,k);

add(r+1,-k);

}int main()

for(int i=1;i<=m;i++)

dfs1(1,0,0);

dfs2(1,1);

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

for(int i=1;i<=p;i++)

else

if(op[0]=='d')

else

if(op[0]=='q')}}

return

0;}

樹鏈剖分 模板

class match node a n struct no no aa n 4 void init void addpage int x,int y void dfs int s,int faa,int h 根節點,父節點和深度的 if max 0 son s sign void dfs2 int...

模板 樹鏈剖分

define maxn 50010 define l u u 1 define r u u 1 1 寫在類裡面爆棧 int n,m,q int tim 時間戳 int num maxn 樹上每個節點的初始值 int siz maxn siz u 表示以u為根的子樹的節點數 int top maxn ...

樹鏈剖分模板

點權模板 1 m a b c將節點a到節點b路徑上所有點都染成顏色c 2 q a b詢問節點a到節點b路徑上的顏色段數量 連續相同顏色被認為是同一段 如 112221 由3段組成 11 222 和 1 const int n 100100 struct edge g n 2 int cnt,head...