日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

树链剖分-学习报告

發布時間:2023/12/3 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 树链剖分-学习报告 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概要

(這是筆者剛學完趁熱寫的博客
由于也是初學,所以可能會對初學讀者比較友好吧
畢竟你不明白的地方我可能也迷惑過)

學完感覺樹鏈剖分的設計真的很巧妙
其主要用途是壓縮樹上路徑
又是一個n到log的優化

原理

先引定義:

設定每個結點所有兒子中,子樹的結點個數最多的兒子為重兒子
重兒子連成的鏈叫做重鏈
每條重鏈深度最小的點叫做重鏈的鏈頭

能得出一個很重要的結論:

從根出發的任意一條路徑經過的重鏈數不超過logm(m為邊數)

這是樹鏈剖分提速的關鍵
這個結論畫個圖就能很容易的看出來(路徑產生斷點必然意味著有一條至少比原路徑結點更多的子樹)

應用

樹鏈剖分常常和dfs序結合
如果再dfs時先dfs重兒子,重鏈的dfs序就是連續的
我們就可以一起進行修改
這樣就可以用線段樹之類的結構進行維護了

實現

那么接下來我們嘗試代碼實現

dfs

先樹上dfs一遍求出每個結點的深度、父親、子樹大小等基本信息
順便把重兒子也求了

void dfs1(int x,int f){size[x]=1;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==f) continue;dep[to]=dep[x]+1;fa[to]=x;dfs1(to,x);size[x]+=size[to];if(!hson[x]||size[to]>size[hson[x]]) hson[x]=to;}return; }

再dfs一遍求dfs序和鏈頭
注意先dfs重兒子

void dfs2(int x,int tp){top[x]=tp;dfs[++tot]=x;pos[x]=tot;a[tot]=b[x];if(!hson[x]) return;dfs2(hson[x],tp);for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==fa[x]) continue;if(to==hson[x]) continue;else dfs2(to,to);}return; }

(dfs數組和pos數組互相映射,按需取食)

修改&查詢

dfs之后就要開始干活了
修改和查詢其實一個道理
兩個點如果鏈頭相同,就說明在同一條重鏈上
直接對兩者之間的dfs區間處理即可
否則就選深度大的那個點,讓它往上跳一條鏈,同時對這條鏈處理
直到兩點在同一條重鏈上為止
對區間的修改查詢當然離不開強大的線段樹啦

void roadchange(int x,int y,int v){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);longchange(1,1,tot,pos[top[x]],pos[x],v);x=fa[top[x]];}if(dep[x]<dep[y]) swap(x,y);longchange(1,1,tot,pos[y],pos[x],v);return; } ll roadask(int x,int y){ll ans=0;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);ans+=longquery(1,1,tot,pos[top[x]],pos[x]); // printf("+=%d %d\n",pos[top[x]],pos[x]);ans%=mod;x=fa[top[x]];}if(dep[x]<dep[y]) swap(x,y);ans+=longquery(1,1,tot,pos[y],pos[x]); // printf("+=%d %d\n",pos[y],pos[x]);return ans%mod; }

線段樹

不知道怎么寫就點這里吧

細節

這是筆者第一次寫的時候遇到的一些小的問題
與你共勉吧

1.線段樹訪問時應該是dfs序小的寫在前,也就是深度小的在前!
2.踩一個坑已經足夠,所以沒有2了

thanks for reading!

總結

以上是生活随笔為你收集整理的树链剖分-学习报告的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。