點分治學習筆記

2021-09-27 05:59:48 字數 1409 閱讀 8710

點分治主要用來處理樹上路徑問題,可以統計樹上點到點的所有路徑,複雜度o(nlogn)

基於樹上的結點進行分治,不斷將一棵樹拆成多顆子樹處理

選擇點時為了防止退化成鏈的情況,如果選點後左右子樹越大,遞迴層數越多,時間越慢,反之則越快,我們每次選擇子樹內的重心

void getroot(int u, int fa) 

f[u] = max(f[u], sum - sz[u]);

if (f[u] < f[root]) root = u;

}

分治時每次選擇當前重心計算結果,遞迴處理子樹,容斥一下結果

void solve(int u) 

}

每次選擇乙個重心之後我們需要統計它到其他的點的路徑,之後兩兩合併,計算對結果的貢獻

void getdis(int u, int dis, int fa) 

}void cal(int u, int dis, int add)

}for (int i = 0; i < 3; ++i) o[i] = num[i] = 0;

}

記錄的例題

poj1741

#include #include #include #include #include using namespace std;

typedef long long ll;

const int maxn = 1e4 + 5;

vector< pair>e[maxn];

int n, k;

int root, sum, vis[maxn], sz[maxn], f[maxn];

int dis[maxn], tot;

ll ans;

void getroot(int u, int fa)

f[u] = max(f[u], sum - sz[u]);

if (f[u] < f[root]) root = u;

}void getdis(int u, int dist, int fa)

}void calc(int u, int dist, int add)

else r--;

}}void solve(int u)

}int main()

ans = 0; sum = n; root = 0; f[0] = 0x3f3f3f;

getroot(1, 0); solve(root);

printf("%lld\n", ans);

}}

點分治學習筆記

關於點分治,其實思想是非常好理解的,模擬在數列上或是在平面上的分治演算法 如歸併排序,平面最近點對等 我們可以從字面上理解該演算法 以乙個點為界限,將一棵樹分成若干個子樹,當劃分到一定規模,就對每個子樹分別進行求解 感性理解就好了 感受乙個演算法最直觀的辦法,就是來看一道模板題。給定一棵有 n 個點...

點分治學習筆記

point divide and rule 澱粉質就是在樹上,依靠不停的遞迴和分治,解決相同的子問題 先來看看模板題 tree 就是找樹上 k 的路徑有多少 我們可以分兩種情況討論 1.經過根節點 p 的路徑 2.不經過根節點 p 的路徑 第二種情況可以通過遞迴來處理,我們直接來討論第一種情況 設當...

點分治學習筆記

銀月城傳送門 集訓day9上午各種神仙分治真心聽不懂,自己頹著把點分治學了,簡單 並不 寫一下再加深一下理解吧。一 點分治是個啥 點分治是通常用來處理樹上路徑統計問題的一種分治方法。尤其適用於大規模的資料處理。時間複雜度最高為o nlogn 例如求樹上兩點間距離,點分治就遠優於dfs求兩點距離 o ...