首页 > 其他分享 >QOJ7206 Triple

QOJ7206 Triple

时间:2024-01-23 18:16:13浏览次数:38  
标签:rt int dep maxn Triple mxd QOJ7206 id

QOJ 传送门

大分讨恶心题。

首先施容斥,变成求 \(\sum |AB| > \max(|AC|, |BC|)\)。

遇到这种三个点的路径问题,可以找出一个点 \(X\),使得 \(A, B, C\) 在 \(X\) 的不同子树内,也就是 \(A \to B, A \to C, B \to C\) 的路径的唯一一个交点 \(X\)。那么:

\[[|AB| > \max(|AC|, |BC|)] = [|AX| + |BX| > \max(|AX| + |CX|, |BX| + |CX|)] = [\min(|AX|, |BX|) > |CX|] \]

考虑先点分治,考虑对于一个分治中心 \(R\),计算 \(A, B, C\) 不是都在同一棵子树的方案。为了方便认为 \(R\) 是单独的一棵子树。

若 \(A, B, C\) 都不在同一棵子树,考虑直接枚举 \(C\),对子树每个点的深度预处理一个后缀和 \(F_d\) 和在每棵子树选两个深度 \(\ge d\) 的点的方案数 \(G_d\),为了容斥算出 \(A, B\) 不在同一棵子树的方案数。需要去除 \(C\) 所在子树对 \(F, G\) 的贡献。

若 \(A, C\) 在同一棵子树(\(B, C\) 一样,贡献 \(\times 2\)),考虑枚举 \(X\) 和 \(|CX|\),那么要求 \(|AX| > |CX|\),可以用长剖计算这样的对数。还要求 \(|BX| > |CX|\),即 \(|BR| + |RX| > |CX|\),即 \(|BR| \ge |CX| - |RX| + 1\)。这部分贡献可以用上部分处理的 \(F\) 数组。

若 \(A, B\) 在同一棵子树,考虑直接枚举 \(X\) 和 \(\min(|AX|, |BX|)\),也可以用长剖计算 \(X\) 子树内 \(A, B\) 的对数使得 \(\min(|AX|, |BX|) = k\)。还要求 \(|CX| < k\),即 \(|CR| \le k - |RX| - 1\)。这部分贡献也可以用第一部分处理的 \(F\) 数组。

于是总时间复杂度为 \(O(n \log n)\)。

注意讨论一些 corner case。

code
#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 100100;

int n;
vector<int> gg[maxn];

int f[maxn], sz[maxn], rt;
bool vis[maxn];

void dfs2(int u, int fa, int t) {
	f[u] = 0;
	sz[u] = 1;
	for (int v : gg[u]) {
		if (v == fa || vis[v]) {
			continue;
		}
		dfs2(v, u, t);
		sz[u] += sz[v];
		f[u] = max(f[u], sz[v]);
	}
	f[u] = max(f[u], t - sz[u]);
	if (!rt || f[u] < f[rt]) {
		rt = u;
	}
}

int D, mxd[maxn], son[maxn], dep[maxn];
vector<int> g[maxn];
// F[d]: 深度 >= d 的点数
// G[d]: 深度 >= d 且在同一棵子树的点对,用于容斥
ll F[maxn], G[maxn], ans;

void dfs3(int u, int fa, int rt) {
	D = max(D, dep[u]);
	if (dep[u] >= (int)g[rt].size()) {
		g[rt].pb(1);
	} else {
		++g[rt][dep[u]];
	}
	mxd[u] = dep[u];
	son[u] = 0;
	for (int v : gg[u]) {
		if (vis[v] || v == fa) {
			continue;
		}
		dep[v] = dep[u] + 1;
		dfs3(v, u, rt);
		if (mxd[v] > mxd[u]) {
			son[u] = v;
			mxd[u] = mxd[v];
		}
	}
}

int tim, h[maxn], id[maxn], p[maxn];

void dfs4(int u, int fa) {
	id[u] = ++tim;
	h[id[u]] = 1;
	p[u] = 1;
	if (son[u]) {
		dfs4(son[u], u);
		p[u] += p[son[u]];
	}
	for (int v : gg[u]) {
		if (v == fa || v == son[u] || vis[v]) {
			continue;
		}
		dfs4(v, u);
		ll s1 = p[u], s2 = 0;
		for (int j = mxd[v] - dep[u]; ~j; --j) {
			s1 -= h[id[u] + j];
		}
		for (int j = mxd[v] - dep[u]; j; --j) {
			// A, C 同子树
			ans += F[max(0, j - dep[u] + 1)] * 2 * (s1 * h[id[v] + j - 1] + s2 * h[id[u] + j]);
			s1 += h[id[u] + j];
			// A, B 同子树
			if (j > dep[u]) {
				ans += (F[0] - F[j - dep[u]]) * 2 * (s1 * h[id[v] + j - 1] + s2 * h[id[u] + j]);
			}
			s2 += h[id[v] + j - 1];
			h[id[u] + j] += h[id[v] + j - 1];
		}
		p[u] += p[v];
	}
	// X = C = u
	ans += 2LL * (p[u] - 1) * F[0];
	// X = R, C = u, A, B 不同子树
	ans += F[dep[u] + 1] * (F[dep[u] + 1] - 1) - G[dep[u] + 1];
}

void dfs(int u) {
	D = 0;
	vis[u] = 1;
	for (int v : gg[u]) {
		if (vis[v]) {
			continue;
		}
		g[v].pb(0);
		dep[v] = 1;
		dfs3(v, u, v);
		for (int i = mxd[v], s = 0; ~i; --i) {
			s += g[v][i];
			F[i] += s;
			G[i] += 1LL * s * (s - 1);
		}
	}
	// X = C = R 且 A, B 不同子树
	ans += F[1] * (F[1] - 1) - G[1];
	++F[0];
	for (int v : gg[u]) {
		if (vis[v]) {
			continue;
		}
		for (int i = mxd[v], s = 0; ~i; --i) {
			s += g[v][i];
			F[i] -= s;
			G[i] -= 1LL * s * (s - 1);
		}
		tim = 0;
		dfs4(v, u);
		for (int i = mxd[v], s = 0; ~i; --i) {
			s += g[v][i];
			F[i] += s;
			G[i] += 1LL * s * (s - 1);
		}
	}
	for (int i = 0; i <= D; ++i) {
		F[i] = G[i] = 0;
	}
	for (int v : gg[u]) {
		if (vis[v]) {
			continue;
		}
		vector<int>().swap(g[v]);
	}
	for (int v : gg[u]) {
		if (vis[v]) {
			continue;
		}
		rt = 0;
		dfs2(v, -1, sz[v]);
		dfs2(rt, -1, sz[v]);
		dfs(rt);
	}
}

void solve() {
	for (int i = 1; i <= n; ++i) {
		vector<int>().swap(gg[i]);
		vis[i] = 0;
	}
	for (int i = 1, u, v; i < n; ++i) {
		scanf("%d%d", &u, &v);
		gg[u].pb(v);
		gg[v].pb(u);
	}
	ans = 0;
	rt = 0;
	dfs2(1, -1, n);
	dfs2(rt, -1, n);
	dfs(rt);
	printf("%lld\n", 1LL * n * (n - 1) * (n - 2) - ans);
}

int main() {
	while (scanf("%d", &n) == 1) {
		solve();
	}
	return 0;
}

标签:rt,int,dep,maxn,Triple,mxd,QOJ7206,id
From: https://www.cnblogs.com/zltzlt-blog/p/17983038

相关文章

  • [ARC155C] Even Sum Triplet 题解
    一道大分类讨论。如果有一个可以交换的段包含奇数,那么你可以把所有奇数移到最左边并任意调整相对顺序,然后回到任意一种有一个可以交换的段包含奇数的状态。这种情况,如果偶数的数量为\(2\),这两个偶数是不能交换相对位置的,有至少\(3\)个偶数就能交换偶数间相对位置。所以只需要......
  • TripleDES在java与c#中的区别
        C#下TripleDES默认支持16位和24位的秘钥,而Java下的DESedeKeySpec就只支持24位,其实怎么说呢,按3DES规范要求,的确其秘钥应该是24位而不是16位的,但16位秘钥可以按前8位+后8位+前8位的规则来升级成24位的秘钥,所以我们只需要简单的通过数组的Copy就可以将16位秘钥升级为24......
  • E. Good Triples
    首先假定已经找到abc符合题目条件。则我们假定a1,a2,a3...;b1,b2,b3...;c1,c2,c3...为abc各个位置上的数字,那么  a1 a2 a3  b1 b2 b3+c1 c2 c3----------------  x1  x2  x3又由digsum等式可知a1+b1+c1+...=x1+x2+x3。那么我们根据竖式不难发......
  • E. Good Triples
    绝,太绝了看我娓娓道来1.如果\(a+b+c\)过程中有进位,那么位数和肯定不等(+1-10)2.由此可知,只要相加过程中没有进位的abc就是合法的3.n的每一位等于abc对应的每一位的和4.最后一步就是排列组合的思维,我真的词穷了。。。代码#include<bits/stdc++.h>usingnamespacestd;#defin......
  • E. Good Triples
    E.GoodTriplesGivenanon-negativeintegernumber$n$($n\ge0$).Let'ssayatripleofnon-negativeintegers$(a,b,c)$isgoodif$a+b+c=n$,and$digsum(a)+digsum(b)+digsum(c)=digsum(n)$,where$digsum(x)$isthesumofdigitsofn......
  • Triple DES 加密解密技术解析
    摘要:本文介绍了TripleDES加密解密技术,通过实例演示了加密和解密过程,并对算法原理进行了简要分析。同时,探讨了TripleDES在现代信息安全领域的应用和局限性。3DES(TripleDES)加密解密--一个覆盖广泛主题工具的高效在线平台(amd794.com)https://amd794.com/tripledesencordec一、......
  • Triple DES 加密解密技术解析
    摘要:本文介绍了TripleDES加密解密技术,通过实例演示了加密和解密过程,并对算法原理进行了简要分析。同时,探讨了TripleDES在现代信息安全领域的应用和局限性。3DES(TripleDES)加密解密--一个覆盖广泛主题工具的高效在线平台(amd794.com)https://amd794.com/tripledesencord......
  • [V8] Double & Triple Equals
    doubleequalsis15timesslowerthantripleequals.Underhooddoubleequalsneedtocall valueOf()functiontoconvertthevalue.({valueOf:()=>3})==3//true({valueOf:()=>3})===3//false ......
  • P9194 [USACO23OPEN] Triples of Cows P 题解
    Description给定一棵初始有\(n\)个点的树。在第\(i\)天,这棵树的第\(i\)个点会被删除,所有与点\(i\)直接相连的点之间都会两两连上一条边。你需要在每次删点发生前,求出满足\((a,b)\)之间有边,\((b,c)\)之间有边且\(a\not=c\)的有序三元组\((a,b,c)\)对数。\(n\leq2......
  • 2023ACMMM_Mutual Information-driven Triple Interaction Network for Efficient Ima
    一.Motivation之前网络存在的缺点:1.使用的有限的频域信息 2. 不充足的信息交互:(1)第一阶段的输出直接作为第二阶段的输入,忽略了中间特征从早期到后期的传播(2)在编码器解码器结构同尺度之间进行特征融合,忽略了阶段内和跨阶段的跨尺度信息交换3. 严重的特征......