1. 程式人生 > 其它 >noip模擬38 c <點分治>

noip模擬38 c <點分治>

點分治

(: 今天考到了,剛被迫學的,所以有解釋不太對的地方還請指教。)

一種高效的優化方式,
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,其實我們把重邊刪去後,原圖就是一棵樹。顏色數較多的邊我們僅需存任意三個顏色即可,也就是保證了至少有一種顏色能夠均不與兩邊匹配,顯然對答案是沒有影響的。
對於轉移,我們想要知道的只是序列左右兩端的顏色,