【LOJ2324】「清華集訓 2017」小 Y 和二叉樹
【題目連結】
【思路要點】
- 答案的第一位一定是編號最小的度數不為 的節點,不妨設為 ,以 為根, 的子樹內編號最小的度數不為 的節點為 。
- 在這個思路上,我們考慮如何比較 和 兩點作為根節點時的答案哪個更優。
、當 ,比較 的 所在子樹 的 和 所在子樹 的 。
、當 ( 同理), 比較 的 所在子樹 的 和 。(實際上不考慮這一點就可以通過原題的資料,但過不了樣例……)- 如此,我們找到了最終答案的根節點, 找到最優答案即可。
- 時間複雜度 。
【程式碼】
#include<bits/stdc++.h> const int MAXN = 1e6 + 5; const int INF = 1e9; using namespace std; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } const int MAXBUF = 1 << 23; char B[MAXBUF], *S = B, *T = B; char getc() { if (S == T) T = (S = B) + fread(B, 1, MAXBUF, stdin); if (S == T) return 0; else return *S++; } template <class T> void read(T &a) { static char c; static int fh; while (((c = getc()) < '0' || c > '9') && c != '-'); if (c == '-') fh = -1, a = 0; else fh = 1, a = c - '0'; while ((c = getc()) <= '9' && c >= '0') a = (a << 3) + (a << 1) + c - '0'; a *= fh; } char Buff[MAXBUF], *st = Buff; template <class T> void write(T a) { if (a == 0) *st++ = '0'; else { if (a < 0) *st++ = '-', a = -a; static char c[20]; static int c0; c0 = 0; while (a) c[c0++] = a % 10 + '0', a /= 10; while (c0--) *st++ = c[c0]; } } int n, k[MAXN], a[MAXN][4], ans[MAXN]; int minnum[MAXN], num[MAXN], tans[MAXN]; int tot, ansroot, vis[MAXN], dp[MAXN], father[MAXN]; void dfs(int pos, int fa) { int tmp = 0; if (fa) tmp = 1; if (k[pos] == tmp) { minnum[pos] = pos; return; } if (k[pos] - tmp == 1) { minnum[pos] = pos; for (int i = 1; i <= k[pos]; i++) if (a[pos][i] != fa) { dfs(a[pos][i], pos); minnum[pos] = min(minnum[pos], minnum[a[pos][i]]); } } else { minnum[pos] = INF; for (int i = 1; i <= k[pos]; i++) if (a[pos][i] != fa) { dfs(a[pos][i], pos); minnum[pos] = min(minnum[pos], minnum[a[pos][i]]); } } } void work(int pos, int fa) { int tmp = 0; if (fa) tmp = 1; if (k[pos] == tmp) { ans[++tot] = pos; return; } if (k[pos] - tmp == 1) { if (minnum[pos] == pos) ans[++tot] = pos; for (int i = 1; i <= k[pos]; i++) if (a[pos][i] != fa) work(a[pos][i], pos); if (minnum[pos] != pos) ans[++tot] = pos; } else { for (int i = 1; i <= k[pos]; i++) if (a[pos][i] != fa && minnum[pos] == minnum[a[pos][i]]) work(a[pos][i], pos); ans[++tot] = pos; for (int i = 1; i <= k[pos]; i++) if (a[pos][i] != fa && minnum[pos] != minnum[a[pos][i]]) work(a[pos][i], pos); } } void getans(int pos) { tot = 0; dfs(pos, 0); work(pos, 0); } void getdp(int pos, int fa) { father[pos] = fa; if (fa == 0) dp[pos] = pos; else dp[pos] = INF; if (k[pos] <= 2) chkmin(dp[pos], pos); for (int i = 1; i <= k[pos]; i++) if (a[pos][i] != fa) { getdp(a[pos][i], pos); chkmin(dp[pos], dp[a[pos][i]]); } } bool tryroot(int pos, int lca) { if (ansroot == 0) { ansroot = pos; return true; } if (lca != ansroot) { int newr = 0, oldr = 0; for (int i = 1; i <= k[lca]; i++) { if (a[lca][i] != father[lca] && vis[a[lca][i]] == 1) oldr = a[lca][i]; if (a[lca][i] != father[lca] && vis[a[lca][i]] == 2) newr = a[lca][i]; } bool ans = dp[newr] < dp[oldr]; if (ans) ansroot = pos; return ans; } else { int tmp = 0; for (int i = 1; i <= k[lca]; i++) if (a[lca][i] != father[lca] && vis[a[lca][i]] == 1) tmp = a[lca][i]; bool ans = tmp < dp[tmp]; if (ans) ansroot = pos; return ans; } } bool getroot(int pos, int fa, int lca) { bool ans = false; vis[pos] = 1; if (fa && k[pos] <= 2) ans |= tryroot(pos, lca); for (int i = 1; i <= k[pos]; i++) if (a[pos][i] != fa) { if (ans) getroot(a[pos][i], pos, pos); else ans |= getroot(a[pos][i], pos, lca); } vis
相關推薦
【LOJ2324】「清華集訓 2017」小 Y 和二叉樹
【題目連結】 點選開啟連結 【思路要點】 答案的第一位一定是編號最小的度數不為 3
【LOJ2323】「清華集訓 2017」小 Y 和地鐵
【題目連結】 點選開啟連結 【思路要點】 很不錯的腦洞題。 附上官方題解。 時間複雜度 O
LOJ2325「清華集訓 2017」小Y和恐怖的奴隸主(期望概率+矩陣快速冪)
LOJ2325「清華集訓 2017」小Y和恐怖的奴隸主 題意: "A fight? Count me in!" 要打架了,算我一個。 "Everyone, get in here!" 所有人,都過來! 小Y是一個喜歡玩遊戲的OIer。一天,她正在
【LOJ2322】「清華集訓 2017」Hello world!
【題目連結】 點選開啟連結 【思路要點】 一個 1
【LOJ2328】「清華集訓 2017」避難所
【題目連結】 點選開啟連結 【思路要點】 令 x
【LOJ2326】「清華集訓 2017」簡單資料結構
【題目連結】 點選開啟連結 【思路要點】 注意到答案是 O
【LOJ2329】「清華集訓 2017」我的生命已如風中殘燭
【題目連結】 點選開啟連結 【思路要點】 一個直觀的思路是模擬該過程,當路上遇到環的時候通過類似取模的手段加速。 注意到每繞一個環
【LOJ2331】「清華集訓 2017」某位歌姬的故事
【題目連結】 點選開啟連結 【思路要點】 注意到若一個位置被兩種音高 a
【LOJ2330】「清華集訓 2017」榕樹之心
【題目連結】 點選開啟連結 【思路要點】 首先,樹是二分圖,只有一側的點可能成為心。 維護每一棵子樹會產生的向下推動的次數可能的最大值
【LOJ2327】「清華集訓 2017」福若格斯
【題目連結】 點選開啟連結 【思路要點】 M
【LOJ2320】「清華集訓 2017」生成樹計數
【題目連結】【思路要點】連上\(a_i\)的限制,題目要求的實際上是\(\sum_{T}\prod_{i=1}^{N}a_i^{d_i}*d_i^{M}\sum_{i=1}^{N}d_i^{M}\)。我們知道樹的Prufer序列與樹點的度數密切相關,因此考慮使用Prufer序
【LOJ2321】「清華集訓 2017」無限之環
【題目連結】 【思路要點】 先說這道題的正解: 將棋盤看做一張二分圖,每一條邊拆成兩個點,分別屬於二分圖的一邊。 我們需要做一件類似於匹配的事情,同一條邊的兩側或是都沒有管道,或是都有管道。 通過合適的建邊我們能夠用最小費用最大流來解決本題。 時間複雜度
【LOJ】#2320. 「清華集訓 2017」生成樹計數
rac res 然而 除了 加法 wap OS 代碼 reg 題解 我,理解題解,用了一天 我,卡常數,又用了一天 到了最後,我才發現,我有個加法取模,寫的是while(c >= MOD) c -= MOD 我把while改成if,時間,少了 六倍。 六倍。 六倍!!
loj#2330. 「清華集訓 2017」榕樹之心【樹形dp】
傳送門 解題思路: 先考慮根是否可行,即步數是否能抵消完。 考慮w[x]w[x]表示xx的子樹內最少的消剩下的點數。 觀察發現,最難消的肯定是sizesize最大的兒子,設為 yy ,而且如果
【LOJ】#2330. 「清華集訓 2017」榕樹之心 -樹形dp
題解 先考慮根的情況(Subtask3Subtask3)。 根的每個兒子及其構成的子樹之間可以互相抵消。 設rem[i]rem[i]表示以ii為根的子樹最少的不能互相抵消的點數。 那
「清華集訓 2017」無限之環
無限之WA https://www.luogu.org/problemnew/show/P4003 本題如果知道是網路流的話,其實建圖不算特別神奇,但是比較麻煩。 資料範圍過大,插頭dp不能處理,而且是一個網格圖,考慮網路流。 先看是不是二分圖? 每個格子只會和相鄰四個格子發生關係 所以,黑白染色
LOJ2321「清華集訓 2017」無限之環
無限之環 題目描述 曾經有一款流行的遊戲,叫做InfinityLoopInfinityLoop,先來簡單的介紹一下這個遊戲: 遊戲在一個 n×mn×m的網格狀棋盤上進行,其中有些小方格中會有水管,水管可能在方格某些方向的邊界的中點有介面,所
「清華集訓2017」榕樹之心
name clear 方向 世界 oid 可行性 pre lin size 「清華集訓2017」榕樹之心 “已經快是嚴冬了,榕樹的葉子還沒落呢……” “榕樹是常綠樹,是看不到明顯的落葉季節的……” “唉……想不到已經七年了呢。榕樹還是當年的榕樹,你卻不是當年的你了……”
【期望+矩陣乘法】LOJ2325 [清華集訓 2017] 小 Y 和恐怖的奴隸主
【題目】 原題地址 BOSS \text{BOSS} BOSS初始有一個
UOJ #36「清華集訓2014」瑪裡苟斯
這怎麼想得到啊......... UOJ #36 題意:求隨機一個集合的子集的異或和的$k$次方的期望值,保證答案$ \lt 2^{63},1 \leq k \leq 5$ $ Solution:$ 首先考慮$ k=1$的時候怎麼做:如果某位上有$ 1$則有$ \frac{1}{2}$的