點分治學習

2022-01-30 13:07:26 字數 1669 閱讀 9506

嗯,蒟蒻我剛學的就記錄一下

以洛谷的tree為模板講解:洛谷題目傳送門

了解點分治之前,首先要知道什麼是重心(要用到)

簡單來說,就是子樹最小的那個節點,我們需要o(n)地找到他來保證複雜度

void get_root(rg int now,rg int fm)

num=max(num,tot-size[now]);//tot是總點數

//tot-size[now]是父親那邊(不是兒子)的「子樹」大小

if(max>num)max=num,root=now;//是否更新

}

個人認為這裡還是比較簡單的,自己畫個圖簡單明瞭了

找到重心後把重心刪掉,變成兩個連通塊,再分別找重心,把重心與之前找的重心相連邊,不斷遞迴建成一棵新樹,就是點分樹

&&優點:嚴格log層(不信自己驗證)

這道題暫時不要用,但是是點分治的乙個重要知識點……

首先了解幾個特點(暫時不用理解,等下自然就懂)

嗯,不想寫了,所以安利一波機房大佬的部落格理解吧,一時半會真的講不清,至少我問了很久才懂(主要是不想畫圖來講解了,畫圖就很容易理解了)

ycb blog

我也推薦幾道題吧,畢竟沒總結良心過不去(其實就是給自己日後複習用的)

#include#include#include#include#include#include#include#include#include#include#include#define rg register

#define il inline

#define lst long long

#define ldb long double

#define n 40050

using namespace std;

const int inf=1e9;

int n,k,cnt,tot,ans;

int max,root,le,ri;

struct edgeljl[n<<1];

int hd[n];

int size[n],vis[n];

int q[n],dis[n];

il int read()

while(ch>='0'&&ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();

return m?-s:s;

}il void add(rg int p,rg int q,rg int o)

;hd[p]=cnt;

}void get_root(rg int now,rg int fm)

num=max(num,tot-size[now]);

if(max>num)max=num,root=now;

}void get_dis(rg int now,rg int fm)

}il int query(rg int now,rg int base)

return res;

}void divide(rg int now,rg int fm)

}int main()

{ n=read();

for(rg int i=1;itree(就在上面)

[國家集訓隊]聰聰可可(題解)

【模板】點分治1(題解)

點分治學習

嗯,蒟蒻我剛學的就記錄一下 以洛谷的tree為模板講解 洛谷題目傳送門 了解點分治之前,首先要知道什麼是重心 要用到 簡單來說,就是子樹最小的那個節點,我們需要o n 地找到他來保證複雜度 void get root rg int now,rg int fm num max num,tot size...

點分治學習

例題 考慮一顆邊權為1的樹上有多少個路徑正好為k的點對。我們考慮乙個這樣的樹,現在問,這個樹上有多少個點對之間的距離為k。首先,我們從根結點開始考慮。那麼我們可以把所有的路徑劃分為兩個部分 1,經過根結點的路徑。2,不經過根結點的路徑。對於第一種路徑,經過根節點,那麼就是x root y。也就是說這...

點分治學習筆記

點分治主要用來處理樹上路徑問題,可以統計樹上點到點的所有路徑,複雜度o nlogn 基於樹上的結點進行分治,不斷將一棵樹拆成多顆子樹處理 選擇點時為了防止退化成鏈的情況,如果選點後左右子樹越大,遞迴層數越多,時間越慢,反之則越快,我們每次選擇子樹內的重心 void getroot int u,int...