[Comet OJ - Contest # 6 D] [48D 2280] Another channel tree disjoint-set title _

Another problem road tree

Subject to the effect :

Data range :


Problem solution :

This question can be found at first glance, our answer is divided into two cases.

The first is at the root of non-convergence, convergence is the second in the root node.

In the first of several attempts to enumerate the end of the round, assuming that the number of the end of the first round of the program is $ i $ $ f_i $, then the answer is always $ \ sum \ limits_ {i = 1} ^ {N - 1} i \ times f_i $ .

Apparently unable to find this $ f_i $ ....

Furthermore, the suffix think this damn thing and it seems better to ask, is $ g _ i = \ sum \ limits_ {j = i} ^ {N - 1} f _ j $.

As we discuss the equivalent to a depth equal to the point, it is not difficult to think of $ bfs $ order.

Not only consider the case of the root node of convergence.

Found that, in fact, a contiguous zone, they are $ i $ not less than a value of time, you can not select a value.

That along with the number of rounds we enumerate increase, these successive intervals there will be some consolidation of cases.

As for when to merge it? In fact, according to the adjacent two points to its $ lca $ depth when relevant (to be equal to the depth of these two points), that is, the difference in depth is exactly equal to the number of rounds, we implement merge operation.

This is not the perfect solution to a non-root confluence.

Consider the root node supposed to converge.

In fact equivalent, as the number of rounds increments, all the depth of not more than $ i $ the point can only choose one, and the root is equivalent to the combined strategy.

In short pass universal disjoint-set to maintain enough.

Code :

#include <bits/stdc++.h>

#define N 200010 

using namespace std;

int head[N], to[N << 1], nxt[N << 1], tot;

struct Node {
	int x, y;
};

vector <Node> v[N];

queue <int> q;

int f[20][N], g[N], F[N], S[N], dep[N], dic[N], n, inv[N];

const int mod = 998244353 ;

typedef long long ll;

char *p1, *p2, buf[100000];

#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )

int rd() {
	int x = 0, f = 1;
	char c = nc();
	while (c < 48) {
		if (c == '-')
			f = -1;
		c = nc();
	}
	while (c > 47) {
		x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
	}
	return x * f;
}

int qpow(int x, int y) {
	int ans = 1;
	while (y) {
		if (y & 1) {
			ans = (ll)ans * x % mod;
		}
		y >>= 1;
		x = (ll)x * x % mod;
	}
	return ans;
}

inline void add(int x, int y) {
	to[ ++ tot] = y;
	nxt[tot] = head[x];
	head[x] = tot;
}

int lca(int x, int y) {
	if (dep[x] < dep[y])   
		swap(x, y);
	for (int i = 19; ~i; i -- ) {
		if (dep[f[i][x]] >= dep[y]) {
			x = f[i][x];
		}
	}
	if (x == y)
		return x;
	for (int i = 19; ~i; i -- ) {
		if (f[i][x] != f[i][y]) {
			x = f[i][x];
			y = f[i][y];
		}
	}
	return f[0][x];
}

void dfs(int p, int fa) {
	v[dep[p]].push_back((Node){1, p});
	f[0][p] = fa;
	for (int i = 1; i <= 19; i ++ ) {
		f[i][p] = f[i - 1][f[i - 1][p]];
	}
	for (int i = head[p]; i; i = nxt[i]) {
		if (to[i] != fa) {
			dep[to[i]] = dep[p] + 1;
			dfs(to[i], p);
		}
	}
}

void bfs() {
	while (!q.empty())
		q.pop();
	q.push(1);
	int cnt = 0;
	while (!q.empty()) {
		int x = q.front();
		q.pop();
		dic[ ++ cnt] = x;
		for (int i = head[x]; i; i = nxt[i]) {
			if (to[i] != f[0][x]) {
				q.push(to[i]);
			}
		}
	}
	for (int i = 1; i < n; i ++ ) {
		if (dep[dic[i]] == dep[dic[i + 1]]) {
			v[dep[dic[i]] - dep[lca(dic[i], dic[i + 1])]].push_back((Node) {dic[i], dic[i + 1]});
		}
	}
}

int find(int x) {
	return F[x] == x ? x : F[x] = find(F[x]);
}

int main() {
	n = rd();
	for (int i = 1; i <= n; i ++ ) {
		F[i] = i;
		S[i] = 1;
	}
	for (int i = 2; i <= n; i ++ ) {
		int x = rd();
		add(x, i);
		add(i, x);
	}
	dfs(1, 1);
	bfs();
	inv[0] = 1;
	for (int i = 1; i <= n; i ++ ) 
		inv[i] = qpow(i, mod - 2);

	// for (int i = 0 ; i <= n; i ++ ) {
	// 	printf("%d ", inv[i]);
	// }
	// puts("");

	int mdl = qpow(2, n);
	for (int i = 1; i < n; i ++ ) {
		g[i] = (mdl - n - 1 + mod) % mod;
		int len = v[i].size();
		for (int j = 0; j < len; j ++ ) {
			int x = v[i][j].x, y = v[i][j].y;
			x = find(x), y = find(y);
			if (x != y) {
				mdl = (ll)mdl * inv[S[x] + 1] % mod * inv[S[y] + 1] % mod;
				F[x] = y; S[y] += S[x];
				mdl = (ll)mdl * (S[y] + 1) % mod;
			}
		}
	}
	int ans = 0;
	for (int i = 1; i < n; i ++ ) {
		ans = (ans + (ll)(g[i] - g[i + 1] + mod) % mod * i % mod) % mod;
	}
	cout << ans << endl ;
	return 0;
}

Summary : Good questions Good questions, thinking this question fill the gap. Key to that is the ability to think, for some this section can only choose one thing to think clearly, so as to merge into a range of issues, which is the key.

Guess you like

Origin www.cnblogs.com/ShuraK/p/11241290.html