總體步驟:init();dfs1(1);
dfs2(1,1);
build(1,1,n);
cl();
dfs1 處理出size[sj](子節點數),son[sj](重兒子),dep[sj](深度),vi[sj](點權,把邊權放在子節點上)。
dfs2 處理出top[sj](所在鏈的鏈首,輕兒子從子節點重新開始,重兒子從父節點繼承),id[sj](點出現的位置,用cnt標記),pos[sj](cnt位置的邊連著哪乙個點)。
id[x]=++cnt;
pos[cnt]=x;
if(son[x]) dfs2(son[x],y);
for(int i=h[x];i!=-1;i=b[i].ne)
if(b[i].v!=fa[x]&&b[i].v!=son[x]) dfs2(b[i].v,b[i].v);
build if(z==y) mx[x]=vi[pos[y]];
這個位置鏈的最大值等於這個位置的鏈所連點的權值。一般線段樹方法建樹。和線段樹有關的陣列要開四倍四倍四倍。。。
cl 分change和query
change 改變的邊編號要按輸入資料檢索,從線段樹上找到這條邊上作為子節點的點改變它的點權。
int now=(b1<<1)-1;
int fr=b[now].u,to=b[now].v;
if(fa[fr]==to) change(id[fr],b2,1,1,n);
else change(id[to],b2,1,1,n);
query query函式即為一般的線段樹查詢,把不在一條鏈上的兩個點向一條鏈上靠攏,時刻注意要求哪點在下層。如果本來就是點權,則id[x]不應該+1且id[x]==id[y]的情況是可行的。
int fx=top[x],fy=top[y],res=1<<31;
while(fx^fy)
{if(dep[fx]dep[y]) jh(x,y);
if(id[x]
因為我太弱了不寫就會很快忘掉qaq
樹鏈剖分 樹鏈剖分講解
好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 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...
樹鏈剖分步驟
deep 記錄該節點的深度 siz 記錄以該節點為根的子樹的節點數 fa 記錄該節點的父親是誰 son 記錄該節點的重兒子是誰 top 記錄該節點所在的重鏈的根節點是誰 w 記錄該節點投影到數軸後的位置 即dfs序,線段樹要用 讀入,用空間池儲存邊 注意是雙向的 第一次dfs 記錄dep,siz,f...
演算法入門 樹鏈剖分 輕重鏈剖分
目錄 3.0 求 lca 4.0 利用資料結構維護資訊 5.0 例題 參考資料 資料結構入門 線段樹 發表於 2019 11 28 20 39 dfkuaid 摘要 線段樹的基本 建樹 區間查詢 單點修改 及高階操作 區間修改 單點查詢 區間修改 區間查詢 標記下傳 標記永久化 閱讀全文 樹鏈剖分用...