noip模擬38 c <點分治>
阿新 • • 發佈:2021-08-13
點分治
(: 今天考到了,剛被迫學的,所以有解釋不太對的地方還請指教。)
一種高效的優化方式,
ICEY :“ 在執行完點分治的操作後,新圖中兩點的lca一定在原圖中兩點間的簡單路徑上。 ”
在點分治優化完後,新圖大致被分為 \(log\) 層,
若把原圖看為一個序列,我們每次把中點當成我們新的分治點,用原分治點向新分治點連邊,然後繼續向下遞迴,直至均被 \(vis\)。大致就是下圖形式,
轉換成樹上,其實我們就是要找子樹中節點 \(size\) 最接近總數一半的一點(也就是樹的重心)作為新的分治點,與序列原理相同。
在建完圖後,我們就得到了大致均衡的新圖,此時對待一些樹上問題我們就可以高效率得求出所需答案。n這麼小?再來10萬!
附點分治的基礎程式碼:
查詢重心
inline void dfsll(int now,int pre,int tot,int &rt) { int maxson=0; size[now]=1; for(re int i=0,to;i<edge[now].size();i++) { if(vis[to=edge[now][i].first]||to==pre) continue; dfsll(to,now,tot,rt); size[now]+=size[to]; cmax(maxson,size[to]); } if(maxson<=tot/2&&tot-size[now]<=tot/2) rt=now; }
好像沒了... 其餘根據題意來好了
本題題解
對於簡單環的最長長度不超過2,其實我們把重邊刪去後,原圖就是一棵樹。顏色數較多的邊我們僅需存任意三個顏色即可,也就是保證了至少有一種顏色能夠均不與兩邊匹配,顯然對答案是沒有影響的。
對於轉移,我們想要知道的只是序列左右兩端的顏色,