樹鏈剖分整理
樹鏈剖分就是把樹拆成一系列鏈,然後用資料結構對鏈進行維護。
通常的剖分方法是輕重鏈剖分,所謂輕重鏈就是對於節點
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...