Query on a tree 樹鏈剖分整理

2022-05-03 10:30:24 字數 2726 閱讀 5972

樹鏈剖分整理

樹鏈剖分就是把樹拆成一系列鏈,然後用資料結構對鏈進行維護。

通常的剖分方法是輕重鏈剖分,所謂輕重鏈就是對於節點

u的所有子結點v,

size[v]

最大的v與u

的邊是重邊,其它邊是輕邊,其中

size[v]是以v

為根的子樹的節點個數,全部由重邊組成的路徑是重路徑,根據**上的證明,任意一點到根的路徑上存在不超過

logn

條輕邊和

logn

條重路徑。

這樣我們考慮用資料結構來維護重路徑上的查詢,輕邊直接查詢。

通常用來維護的資料結構是線段樹,

splay

較少見。

具體步驟

預處理第一遍

dfs

求出樹每個結點的深度

dep[x]

,其為根的子樹大小

siz[x]

,其重兒子,以及祖先的資訊

fa[x]表示x

的直接父親,

第二遍

dfs

根節點為起點,向下拓展構建重鏈

選擇最大的乙個子樹的根繼承當前重鏈

其餘節點,都以該節點為起點向下重新拉一條重鏈

搞出top[x]

,top[x]表示x

所在鏈的端點

給每個結點分配乙個位置編號,每條重鏈就相當於一段區間,用資料結構去維護。

搞出pos[x],pos[x]

x為下端點的標號(一般不維護邊)

把所有的重鏈首尾相接,放到同乙個資料結構上,然後維護這乙個整體即可

修改操作

1、單獨修改乙個點的權值    //

例題中沒用

根據其編號直接在資料結構中修改就行了。

2、修改點u和點

v的路徑上的權值(1

)若u和v

在同一條重鏈上

直接用資料結構修改

pos[u]

至pos[v]

間的值。(2

)若u和v

不在同一條重鏈上

一邊進行修改,一邊將u和

v往同一條重鏈上靠,然後就變成了情況(1)。

查詢操作

查詢操作的分析過程同修改操作

題目不同,選用不同的資料結構來維護值,通常有線段樹和

splay

例題、spoj 305:query on a tree

題意:10000個點的樹,有邊權(<=1000000),支援兩個操作:

1、change i ti 把第i條變的權改為ti

2、query a b 查詢a,b兩點間路徑上的最大邊

20組資料

#include#include

#include

#define lc k<<1

#define rc k<<1|1

#define in inline

#define r register

using

namespace

std;

const

int n=1e4+10

;in

intread()

while(ch>='

0'&&ch<='9')

return f?x:-x;

}struct

nodee[n

<<1

];int

n,t,tot,num,head[n],fa[n],top[n],pos[n],dep[n],siz[n],son[n];

int a[n<<2

];void add(int x,int y,int

z)void dfs(int u,int f,int

de) }

}}void getpos(int u,int

tp) }

}void change(int k,int l,int r,int pos,int

val)

int mid=l+r>>1

;

if(pos<=mid) change(lc,l,mid,pos,val);

else change(rc,mid+1

,r,pos,val);

a[k]=max(a[lc],a[rc]);

}int query(int k,int l,int r,int x,int

y)int find(int u,int

v) ans=max(ans,query(1,1

,num,pos[tp1],pos[u]));

u=fa[tp1];tp1=top[u];

}if(u==v) return

ans;

if(dep[u]>dep[v]) swap(u,v);

return max(ans,query(1,1,num,pos[u]+1

,pos[v]));

}void

cl()

intmain()

dfs(

1,0,1

); getpos(

1,1);

for(int i=1,t=(n-1)*2;i2

)

char ch[20

];

for(int

x,y;;)

else}}

return0;

}

Query on a tree 樹鏈剖分

題意 給你一棵樹,和樹上邊的權值,在有q組詢問a,b,問你從節點a 節點1的路徑上,不小於b的最大的邊的權值是多少,輸出 離線維護最大值線段樹即可 模板題 includeusing namespace std input by bxd define rep i,a,b for int i a i b...

樹鏈剖分 375 Query on a tree

樹鏈剖分並不是乙個複雜的演算法或者資料結構,只是能把一棵樹拆成鏈來處理而已,換一種說法,樹鏈剖分只是 資料結構 演算法在樹上的推廣,或者說,樹鏈剖分只是把樹hash到了幾段連續的區間上。主要參考kuangbin 以及 第二個其中的修改操作的解釋好像有問題,其例子中查詢11和10 的實際的遍歷和他的解...

樹鏈剖分 樹鏈剖分講解

好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 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...