知識點 點分治 動態點分治

2022-05-19 02:14:21 字數 2058 閱讀 1660

點分治:

優雅地暴力解決一類不帶修改的樹上路徑問題。

每次找原樹的重心,以重心為根暴力列舉當前子樹內的所有點算答案,然後繼續遞迴子樹。

這個東西最多會遞迴$\log$層,所以複雜度是$o(n\log)$的。

#include#include

#include

#include

#define maxn 100005

#define maxm 500005

#define inf 0x7fffffff

#define ll long long

using

namespace

std;

int n,m,k,hd[maxn],to[maxn<<1],nxt[maxn<<1],cst[maxn<<1

];int

rt,ans,num,siz[maxn],d[maxn],q[maxn],tot,mnsiz,cnt;

bool

vis[maxn];

inline

intread()

inline

void addedge(int u,int v,int

w)inline

void getrt(int u,int

fa) mx=max(mx,tot-siz[u]);

if(mxmx;

return;}

inline

void getdis(int u,int

fa)

return;}

inline

int calc(int u,int

val)

return

res;

}inline

void dfs(int

u)

return;}

intmain()

while(m--)

return0;

}

點分治動態點分治(點分樹):

解決帶修改的點分治問題。

按dfs的順序把點分治的所有重心連成一棵樹,每次修改在樹上跳fa更新貢獻。

注意這棵樹破壞了原樹的結構,所以需要容斥的地方可能要單獨維護。

複雜度$o(n\log)$。(luogu這麼喜歡模板題卡常啊?)

#include#include

#include

#include

#define maxn 100005

#define maxm 500005

#define inf 0x7fffffff

#define ll long long

using

namespace

std;

int n,m,k,hd[maxn],to[maxn<<1],nxt[maxn<<1],cst[maxn<<1

];int

rt,ans,num,siz[maxn],d[maxn],q[maxn],tot,mnsiz,cnt;

bool

vis[maxn];

inline

intread()

inline

void addedge(int u,int v,int

w)inline

void getrt(int u,int

fa) mx=max(mx,tot-siz[u]);

if(mxmx;

return;}

inline

void getdis(int u,int

fa)

return;}

inline

int calc(int u,int

val)

return

res;

}inline

void dfs(int

u)

return;}

intmain()

while(m--)

return0;

}

動態點分治

點分治 動態點分治

實在拖得太久了。先扔掉資料 分治的核心是盡量把乙個整體分成接近的兩個部分,這樣遞迴處理可以讓複雜度從n 變成nlogn。兩個問題,如何區分和如何算答案。對於第乙個問題,重心,然後就是找重心的方法,兩個dfs,對於第二個問題,對於每個重心算當前塊中每個點到重心的答案,然後由重心分開的塊要把多餘的資訊去...

點分治與動態點分治

點分治一般是用於解決樹上路徑問題。樹的重心 把重心這個點割掉後,使所形成的最大的聯通塊大小最小的點。可以證明重心子樹的大小最大不會超過 n over 2 重心可以通過 dfs 一遍求出。maxsiz x 表示割掉點x後所形成的的最大的聯通塊的大小 void dfs int x,int fa max ...

動態點分治

由於蒟蒻太遜,現在才開始學動態點分治,寫乙個 blog 吧。動態點分治是利用點分治的過程,建成一顆由子樹重心連線而成的點分樹,這棵樹的高度為 log n 級別的,因此可以通過暴力跳父親完成修改操作。建立點分樹的過程,就是按照點分治的流程,記錄上級重心並連線,即可獲得一棵點分樹。點分樹的結構與原樹不相...