Tony102's Blog - Codechef
type: channel
link: https://tony102.com/index.php/tag/Codechef/
items: Codechef CTREE Chef and Chefcoin

Codechef CTREE Chef and Chefcoin
type: item
date: 2021-09-16T19:17:00+08:00
description: Link中文题面链接Sol先来考虑一个简单版本的问题：我们只有一个北国银行。答案是：$$ \sum\limits_{(x,fa)\in E} w \cdot min(size_{x},S - size_{x}) $$证明：不妨设树根为$1$。在上面的表达式中，$size_{x}$ 表示的是在 $x$ 子树中居民的数量，$S$表示树中居民的总数量。考虑如何计算所有居民接收到一枚钟离盾的总时间：对于每一条边，它的贡献为 $w$ $*$ 通过这条边的居民的数量的总和，即对于每一条边 $(x, fa, w)$，我们有两种选择：一是选择子树内的所有居民通过该边（此时北国银行在子树外），故此部分贡献为 $w \cdot size_{x}$；二是选择 $x$ 的子树外的所有点上的居民通过该边进入 $x$ 的子树领取钟离盾（此时北国银行在子树内）。两种方式取 $min$ 即可。考虑最终北国银行放置的位置，会有一条没有居民过的边。那么可以枚举该边并将此边断开，使原树分成两个树，再通过上面的方法对两棵树的答案独立计算。时间复杂度为 $O(n^2)$。定义 $in_v$ 为 DFS 时进入$v$ 点的时间戳，$out_v$ 为 DFS 时离开 $v$ 点的时间戳。假设只放置一个北国银行，我们就应该找到对于所有边 $e(v, to, w)$ ：$\sum\limits_{e\in E} w \cdot min(size_{to}, S - size_{to})$ 的总和。考虑 $size_{to}$ 和 $S - size_{to}$ 什么时候会算到贡献里：$w \cdot min(size_{to}, S - size_{to})$ 为 $w \cdot size_{to}$ 当且仅当 $size_{to} \leq \frac{S}{2}$， 为 $w \cdot (S - size_{to})$ 当且仅当 $size_{to} > \frac{S}{2}$。回到 $O(n^2)$ 的解法。我们在 DFS 时在树中移去边 $(v, to, w)$ 。现在有两棵子树，大小分别为：$X = size_{to}, Y = size_{1} - size_{to}$。 考虑分别在 $X, Y$ 两棵树上解决问题。第一部分先计算 $to$ 子树中的点的答案： $w \cdot min(size_{to}, X - size_{to})$ 的值的和。我们可以计算出 $w \cdot size_{to} (\forall size_{to} \leq \frac{X}{2}) + w \cdot X (\forall size_{to} > \frac{X}{2}) - w \cdot size_{to} (\forall size_{to} > \frac{X}{2})$。剩余的部分就是要求出区间 $[l,r]$ 内所有数字 $\leq K$ 的和。可以把区间 $[in_{to}, out_{to}]$ 内的点的 $w$ 和 $w \cdot size_{to}$ 丢进两个树状数组，分别统计两类的答案即可。$to$ 的子树以外的部分做法也很类似。注意要将这些操作在区间 $[1, in_{to} - 1]$ 和 $[out_{to} + 1, n]$ 和子树 $Y$ 上完成。除了从根节点开始的链到 $v$ （ 包括 $to$ 的子树中的节点）。在这条链上 $size_u$ 单调递减，所以用双指针并且记录前缀和。可以减去我们要为 $\leq \frac{Y}{2}$ 计算的部分。同样对 $size_{1} - size_{u}$ 做这样的步骤。最后加上我们需要的 $> \frac{Y}{2}$ 的部分，这部分在这条链上递增。时间复杂度和空间复杂度均为 $O(n \log n)$ 。Code#include <bits/stdc++.h> using namespace std; typedef long long LL; const int SIZE = 5e4 + 5, SIZE_N = 2.5e5 + 5; const LL inf = 9e18; int n, rt, num, tim, tot; int head[SIZE], a[SIZE], dep[SIZE], f[SIZE][18], dfn[SIZE], id[SIZE], lg[SIZE], fx[SIZE], s[SIZE], b[SIZE]; LL S, siz[SIZE], y[SIZE], z[SIZE], ans[SIZE], c[SIZE], C[SIZE]; struct node { int to, v, nxt; } edge[SIZE << 1]; struct ask {…