點這裡看題目。
原來資料的奇怪結尾就可以拿來判斷特徵呀
太簡單就不說了。
考慮完全二叉樹怎麼做。
這裡需要注意一點,就是:\(n=262143=2^-1\) ,也就是說,資料實際上就是一棵滿二叉樹。
由於滿二叉樹具有極強的對稱性,我們不難想到這樣解決:
首先,答案一定包含 \(\frac-rt\),其中 \(rt\) 是樹的根。
考慮根的左子樹上深度為 \(d\) (根的深度為 \(0\) )的節點,我們可以任選乙個,計算出拆掉它和它父親之間的邊後,父親那顆子樹的貢獻\(t\)。那麼答案就應該加上 \(2^\times t\) 。右子樹同理。
這樣計算就是 \(o(n\log_2n)\) 的。
這個部分還可以推出通項公式。該方法的依據是:
1 . 每個點拆掉了它和它父親之後,它就是自己那部分的重心。
2 . 拆掉左邊的任何邊,根的右兒子一定是重心;拆掉右邊,左兒子一定是重心。
3 . 拆掉乙個葉子和它父親連的邊,根一定是重心。
然後就可以利用上述依據 \(o(n)\) 計算答案了。
為了方便,以下設 \(siz_u\) 表示 \(u\) 的子樹的大小。
首先我們需要非常重要的一點:
對於在乙個大小為 \(n\) 的樹上的點 \(u\) ,若 \(n-siz_u\le \lfloor\frac n 2\rfloor\) ,且它不是重心,那麼重心一定在 \(u\) 的重子樹內。
看起來很好理解吧?考慮簡單地說明一下。
假如 \(u\) 有 \(k\) 個重兒子,那麼每個重兒子的 \(siz\le \frac k\le \lfloor\frac n 2\rfloor\) 。那麼 \(u\) 就是重心,與假設不符,因而 \(u\) 只有乙個重兒子。
同理可以說明, \(u\) 的重兒子的大小 \(>\lfloor\frac n 2\rfloor\) 。也即是說,對於 \(u\) 的非重兒子 \(v\) ,一定有 \(siz_v<\lfloor\frac n 2\rfloor\rightarrow n - siz_v>\lfloor\frac n 2\rfloor\) 。所以重心一定在 \(u\) 的重兒子裡面。
看看我們得到了什麼?
如果 \(u\) 滿足 \(n - siz_u\le \lfloor \frac n 2\rfloor\) ,那麼:
1 .\(u\) 只有乙個重兒子。
2 .要麼 \(u\) 是重心,要麼重心在 \(u\) 的重子樹里。
3 . 如果 \(u\) 是滿足性質的最深的點,那麼 \(u\) 就是重心,且 \(u\) 的父親可能是重心。
第三條可以結合第二條推出。
也就是說:第
一、二條告訴了我們重心的明確方向,第三條告訴了我們重心的判斷標準,並且它還存在單調性。
那我們可以幹什麼了?
倍!增!呀!
以上三條直接教會我們,只要我們能處理出 \(u\) 的朝向重兒子的倍增陣列,我們就可以快速地從樹根開始求重心。
這樣我們就可以在知道倍增陣列後 \(o(\log_2n)\) 地求出重心。那麼我們只需要列舉每一條邊,維護倍增陣列並計算重心即可。由於邊原本可能是無序的,因而我們需要進行 dfs ,並中途維護資訊(本質上還是在 「 換根 」 ),然後就可以倍增出重心了。
時間複雜度是 \(o(n\log_2n)\) 。
int p[maxn], pos[maxn];
int head[maxn], deg[maxn];
void dfs( const int u, const int fa )
}int main()
ll ans = 1ll * n * ( n + 1 ) / 2 - p[1];
ans += 1ll * n / 2 * ( p[2] + p[3] );
ans += 1ll * ( n / 2 + 1 ) * p[1];
//...
}
typedef long long ll;
const int maxn = 3e5 + 5, maxlog = 20;
template_t max( const _t a, const _t b )
int jump[maxn][maxlog];
int hs[maxn], phs[maxn], fath[maxn], siz[maxn];
ll ans;
void addedge( const int from, const int to )
void init( const int u )
void dfs( const int u, const int fa )
jump[u][0] = hs[u];
init( u );
}bool chk( const int u, const int all )
void calc( const int u, const int fa )
}void init()
int main()
CSP2019樹的重心
題解 csp2019d2t3 首先我們要明確乙個性質,那就是對於一棵樹的任何乙個節點來說,如果這個點不是重心,那麼這棵樹的重心就一定在這個節點的以重兒子為根節點的子樹裡 證明顯而易見,因為該點不是重心所以siz 重兒子 一定大於 lfloor frac rfloor 另外還有乙個重心的定義 重心所有...
CSP2019 樹的重心 解題報告
csp2019 樹的重心 t 組資料 1 le t le 5 每次給定一棵 n 個點的樹 1 le n le 299995 設 e 為樹的邊集,v x,v y 分別為刪去邊 x,y 後 點 x 所在的點集和點 y 所在的點集.求 sum left sum x 是 v x 的重心 x sum y 是 ...
CSP2019 樹的重心(樹的重心 倍增 換根)
當年我做這道題時還太嫩了,只能想到暴力。其實如果會了更高的科技這道題只要稍微對暴力優化一下就能ac 我也不會含淚75pts了 廢話不說了,暴力的思路就是列舉每一條邊然後求兩個子樹的重心。直接求重心的複雜度是 o n 的,我們考慮優化到 o log 我們想要求以 x 為根的子樹的重心,首先有個引理 這...