1. 程式人生 > >【LOJ2324】「清華集訓 2017」小 Y 和二叉樹

【LOJ2324】「清華集訓 2017」小 Y 和二叉樹

【題目連結】

【思路要點】

  • 答案的第一位一定是編號最小的度數不為 3 3 的節點,不妨設為 r o
    o t root
    ,以 r o o t
    root
    為根, i i 的子樹內編號最小的度數不為 3 3
    的節點為 d p i dp_i
  • 在這個思路上,我們考慮如何比較 x x y y 兩點作為根節點時的答案哪個更優。
    1 1 、當 l c a ( x , y ) x , y lca(x,y)\ne x,y ,比較 l c a ( x , y ) lca(x,y) x x 所在子樹 l x lx d p l x dp_{lx} y y 所在子樹 l y ly d p l y dp_{ly}
    2 2 、當 l c a ( x , y ) = x lca(x,y)= x = y =y 同理), 比較 l c a ( x , y ) lca(x,y) y y 所在子樹 l y ly d p l y dp_{ly} l y ly 。(實際上不考慮這一點就可以通過原題的資料,但過不了樣例……)
  • 如此,我們找到了最終答案的根節點, O ( N ) O(N) 找到最優答案即可。
  • 時間複雜度 O ( N ) O(N)

【程式碼】

#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清華集訓 2017Y恐怖的奴隸主(期望概率+矩陣快速冪)

LOJ2325「清華集訓 2017」小Y和恐怖的奴隸主 題意: "A fight? Count me in!" 要打架了,算我一個。 "Everyone, get in here!" 所有人,都過來! 小Y是一個喜歡玩遊戲的OIer。一天,她正在

LOJ2322清華集訓 2017Hello 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}$的