筆記 樹鏈剖分

2022-01-14 01:16:30 字數 2186 閱讀 2118

洛谷-樹鏈剖分模板

前置芝士:鏈式前向星,線段樹,dfs序

這裡寫的是重鏈剖分。

參考部落格指盜圖**: x正義小學生x

樹鏈剖分可以把一棵樹「投影「到乙個序列上,然後用線段樹維護一些東西。

通過重兒子的性質來保證時間複雜度。

我們首先使用兩次dfs進行預處理,將樹投影到序列上。

對於乙個有兒子的節點,我們定義它最大的兒子為重兒子。

圖中,3,6,10,5,8就是重兒子。

我們稱像1-3-6-10,2-5,4-8這樣的為一條重鏈。

顯然會形成很多條重鏈,每個點屬於且只屬於一條重鏈。

我們定義乙個陣列 \(top_x\) 表示 \(x\) 所在的重鏈的最淺節點。

在第一次dfs中,我們求出每個點的深度dep,父親節點fa,子樹大小sz,重兒子。

在第二次dfs中,我們求出每個點的dfs序(時間戳就是在新序列裡的位置),並且儲存新序列,建線段樹。注意要儲存每個樹上的點 對應在序列裡的位置 。稱為 \(id_x\)

預處理之後,就要對付詢問。

詢問和修改子樹很顯然,是詢問和修改序列 \([id[x],id[x]+sz[x]-1]\)

鏈怎麼辦呢?樹鏈剖分,意思是將鏈剖開成多個(一條重鏈 或者 一條重鏈的一部分)。

設鏈的兩頭為 \(x\) 和 \(y\) ,

務必注意update的時候兩點的位置!

void updrange(int x,int y,int z)
怎麼保證時間複雜度是

​ 也就是說,根到乙個點最多 \(log n\) 條輕邊。

線段樹有乙隻log,剖鏈會剖成的條數也有乙隻log,一共兩隻log。

時間複雜度 \(o(nlog^2n)\)

#includeusing namespace std;

const int n=1e5+10;

typedef long long ll;

int n,m,r,p;

int e,to[n<<1],nxt[n<<1],hd[n];

int tim,sz[n],dep[n],fa[n],top[n],son[n],id[n];

ll stval[n],fnval[n];

struct post[n<<2];

void add(int a,int b)

void pushup(int rt)

void pushdown(int rt)

}void build(int rt,int l,int r)

int mid=l+r>>1;

build(rt<<1,l,mid);

build(rt<<1|1,mid+1,r);

pushup(rt);

}void update(int rt,int l,int r,int l,int r,ll val)

pushdown(rt);

int mid=l+r>>1;

if(l<=mid) update(rt<<1,l,mid,l,r,val);

if(r>mid) update(rt<<1|1,mid+1,r,l,r,val);

pushup(rt);

}ll query(int rt,int l,int r,int l,int r)

void dfs1(int u,int fat)

return;

}//dep,fa,子樹大小(含它自己),重兒子編號son

void dfs2(int u,int topf)

return;

}//新編號,賦值到新編號上,所在鏈的頂端,處理每條鏈

void updrange(int x,int y,int z)

ll qrange(int x,int y)

void updson(int x,int z)

ll qson(int x)

int main()

dfs1(r,0); dfs2(r,r);

build(1,1,n);

for(int i=1,tp,x,y;i<=m;i++) else if(tp==2) else if(tp==3) else

}

return 0;

}

筆記 樹鏈剖分

樹鏈剖分 對於每個結點 連線子節點多的那個子樹的邊叫做重邊 重邊連起來成鏈 叫重鏈 不止是只有一條重鏈 使用線段樹或者其他的資料結構存重鏈 用此資料結構進行操作 兩個dfs操作 第乙個dfs 求出重鏈 深度dep陣列 父節點fa陣列 和每個結點的子結點個數size陣列 知道了size才可以求出重鏈 ...

樹鏈剖分 樹鏈剖分講解

好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 vector v maxn int size maxn dep maxn val maxn id maxn hson maxn top maxn fa maxn 定義 int edge 1,num 1 struct tree e ma...

樹鏈剖分筆記 (戳)

對於樹鏈剖分,看到大佬紛紛各種躺切內心很是惶恐,於是跪著請教大佬之後把自己的一點感悟發出來以防以後忘了qwq 指一種對樹進行劃分的演算法,它先通過輕重邊剖分將樹分為多條鏈,保證每個點屬於且只屬於一條鏈,然後再通過資料結構 樹狀陣列 sbt splay 線段樹等 來維護每一條鏈 常見的剖分的方法是輕重...