點分治,運用了分而治之的思想,每次算出根及不同子樹之間的貢獻,再將每棵子樹看作一棵新的樹,以重心為根繼續遞迴。
其好處主要是將遞迴層數限制在\(o(log_n)\)下,且每次最多不會遍歷超過n個點,使總時間在\(o(log_n)\)下。
1.找重心:(分為get_size()[可以不做]和find_root()兩部分)
2.算貢獻:(get_ans())
3.繼續遞迴。
#includeusing namespace std;
const int n=10006,maxn=1e7+1;
int n,m,t1,t2,t3,rt=0,cnt=0,ans=0,sum,v[n],head[n],siz[n];
int judge[maxn],dis[n],q[n],ask[n],task[n],num[n],maxp[n];
struct edgee[n<<1];
inline void add(int u,int v,int w)
inline int read()
while(ch>='0'&&ch<='9') t=(t<<3)+(t<<1)+(ch-48),ch=getchar();
return f*t;
}void find_root(int x,int fa)
maxp[x]=max(maxp[x],sum-siz[x]);
if(maxp[rt]>maxp[x]) rt=x;
}void get_dis(int x,int fa)
}void get_ans(int x)
for(int i=1;i<=num[0];++i) judge[num[i]]=0;
}void work(int x)
}int main()
return 0;
}
點分治學習筆記
點分治主要用來處理樹上路徑問題,可以統計樹上點到點的所有路徑,複雜度o nlogn 基於樹上的結點進行分治,不斷將一棵樹拆成多顆子樹處理 選擇點時為了防止退化成鏈的情況,如果選點後左右子樹越大,遞迴層數越多,時間越慢,反之則越快,我們每次選擇子樹內的重心 void getroot int u,int...
點分治學習筆記
關於點分治,其實思想是非常好理解的,模擬在數列上或是在平面上的分治演算法 如歸併排序,平面最近點對等 我們可以從字面上理解該演算法 以乙個點為界限,將一棵樹分成若干個子樹,當劃分到一定規模,就對每個子樹分別進行求解 感性理解就好了 感受乙個演算法最直觀的辦法,就是來看一道模板題。給定一棵有 n 個點...
點分治學習筆記
point divide and rule 澱粉質就是在樹上,依靠不停的遞迴和分治,解決相同的子問題 先來看看模板題 tree 就是找樹上 k 的路徑有多少 我們可以分兩種情況討論 1.經過根節點 p 的路徑 2.不經過根節點 p 的路徑 第二種情況可以通過遞迴來處理,我們直接來討論第一種情況 設當...