不做筆記的後果是我完全忘記了我在5個月前就學過點分治(去洛谷做題才發現的).....
點分治大概是用於樹上路徑的求解。
點分治分4步走:
1,對當前子樹找重心//固定
void getroot(int u,int2,把樹上距離(邊權)存進臨時陣列//根據實際需要稍作修改 。。。比如臨時陣列需要的不是樹上距離fa) ms[u]=max(ms[u],tsiz-siz[u]);
if(ms[u]u;
}
void getdis(int u,int fa,int3,用於divide函式分層解決的solve函式//不同題都不大相同d)}
ans是區域性變數。
int solve(int u,int4,divide函式,找重心,遞迴,分層求解d)
tsiz最初等於n。ans是全域性變數。
void divide(int模板例題u)
return
;}
洛谷p4178 tree 找樹上距離小於或等於固定值k的所有點對數
#include#define debug printf("!");view codeusing
namespace
std;
typedef
long
long
ll;const
int maxn=1e5+50
;const
int inf=0x3f3f3f3f
;int
k,ans;
struct
p;vector
p[maxn];
intcnt,dis[maxn],siz[maxn],ms[maxn],vis[maxn],tsiz,root;
void getroot(int u,int
fa) ms[u]=max(ms[u],tsiz-ms[u]);
if(ms[root]>ms[u])root=u;
}void getdis(int u,int fa,intd)}
int solve(int u,int
d)
return
ans;
}void divide(intu)}
intmain()
); p[v].push_back(p);
}scanf("%d
",&k);
root=0;ms[0]=tsiz=n;getroot(1,0
);divide(root);
printf(
"%d\n
",ans);
}
hncpc 2019找樹上距離為2019的倍數的所有點對數
#include#define debug printf("!");view codeusing
namespace
std;
typedef
long
long
ll;const
int inf=0x3f3f3f3f
;const
int maxn=1e6+50;
struct
p;vector
p[maxn];
intans;
intsiz[maxn],ms[maxn],vis[maxn],root,cnt,tsiz;
void getroot(int u,int
fa) ms[u]=max(ms[u],tsiz-siz[u]);
if(ms[u]u;}
inty[maxn],ny[maxn];
void getdis(int u,int
fa)}
int solve(int u,int
w)void divide(int
u)
return;}
intmain()
for(i=1;i)
);p[v].push_back(p);
}root=0;ms[0]=tsiz=n;getroot(1,0
); divide(root);
printf(
"%d\n
",ans);}}
點分治學習筆記
點分治主要用來處理樹上路徑問題,可以統計樹上點到點的所有路徑,複雜度o nlogn 基於樹上的結點進行分治,不斷將一棵樹拆成多顆子樹處理 選擇點時為了防止退化成鏈的情況,如果選點後左右子樹越大,遞迴層數越多,時間越慢,反之則越快,我們每次選擇子樹內的重心 void getroot int u,int...
點分治學習筆記
關於點分治,其實思想是非常好理解的,模擬在數列上或是在平面上的分治演算法 如歸併排序,平面最近點對等 我們可以從字面上理解該演算法 以乙個點為界限,將一棵樹分成若干個子樹,當劃分到一定規模,就對每個子樹分別進行求解 感性理解就好了 感受乙個演算法最直觀的辦法,就是來看一道模板題。給定一棵有 n 個點...
點分治學習筆記
point divide and rule 澱粉質就是在樹上,依靠不停的遞迴和分治,解決相同的子問題 先來看看模板題 tree 就是找樹上 k 的路徑有多少 我們可以分兩種情況討論 1.經過根節點 p 的路徑 2.不經過根節點 p 的路徑 第二種情況可以通過遞迴來處理,我們直接來討論第一種情況 設當...