[NFLS 1462/4] 机房网络 题解

大意

给定一棵树, 有点权, 求两两间点权互质的点的距离之和.

题解

数论

考虑使用容斥.

p1,p2,,pkp_1, p_2, \cdots , p_k1max(ai)1 \to \max(a_i) 中的质数.

PxP_x 为树中两个点间点权的 gcd 为 xx 的倍数的路径集合, d(P)d(P)PP 的所有路径的长度之和.

那么

res=d(P1)d(Pp1Pp2Ppk)=d(P1)d(Ppi)+d(PpiPpj)+d(PpiPpjPpl)=d(P1)d(Ppi)+d(Ppipj)d(Ppipjpl)(ijl)\text{res} = d(P_1) - d(P_{p_1} \cup P_{p_2} \cup \cdots \cup P_{p_k}) = d(P_1) - d(P_{p_i}) + d(P_{p_i} \cap P_{p_j}) + d(P_{p_i} \cap P_{p_j} \cap P_{p_l}) \cdots = d(P_1) - d(P_{p_i}) + d(P_{p_i p_j}) - d(P_{p_i p_j p_l}) \cdots (i \not= j \not= l)

观察上式的系数以及 PxP_x 中的 xx 可以发现, x=1x = 1 时, 系数为 11, xx 有一个因数时, 系数为 1-1, 两个为 11, 三个为 1-1, 同时不存在 xx 有两个及以上因数的项.

可以发现符合莫比乌斯函数的性质.

所以

res=i=1max(aj)μ(i)d(Pi)\text{res} = \sum_{i = 1}^{\max(a_j)} \mu(i) \cdot d(P_i)

树论

现在要求 d(Px)d(P_x).

可以用树上启发式合并.

disxdis_x 为当前记录的子树中, xvalvx \mid val_vudepv\sum_u dep_v.

那么, 点 uu 的贡献为:

yvaluμ(i)(disx+depu2deplca)\sum_{y \mid val_u} \mu(i) \cdot (dis_x + dep_{u} - 2 \cdot dep_{lca})

[NFLS 1459/6] 魔兽地图 题解

大意

给定若干物品, 一些物品可以直接购买, 不过有数量限制, 另一些物品需要若干其他的物品合成得到, 每个物品都有价值, 被合成消耗的物品不算价值, 给出购买的价钱限制, 求价值最大, 保证合成的方式构成森林.

题解

这题与其他的背包题不同的是, 需要分开来考虑用来用的和用来合成的, 需要加一个维度.

fu,p,kf_{u, p, k} 为考虑到 uu 这个物品, pp 个用来合成, 花费 kk 的最大价值.
qq 为购买或者从下级合成而来的个数.

对于购买的物品:

fu,p,qcostu=valu(qp), pqlimuf_{u, p, q \cdot cost_u} = val_u \cdot (q - p), \ p \le q \le lim_u

对于合成的物品:

fu,p,k=max((vson(u),k=kvfv,qcnt(v),kv)+valu(qp), pq)f_{u, p, k} = max( (\sum_{v \in son(u), k = \sum k_v} f_{v, q \cdot cnt(v), k_v}) + val_u \cdot (q - p) , \ p \le q )

其中 cnt(v)cnt(v) 表示合成 uu 需要 cnt(v)cnt(v) 个物品 vv.

合成的物品可以分别考虑需要的各个物品,
先枚举 qq , 再枚举 vson(u)v \in son(u).

gk=max0kkgk+fv,cnt(v)q,kkg_{k} = \max_{0 \le k' \le k} g'_{k'} + f_{v, cnt(v)\cdot q, k - k'} \newline

fu,p,k=max{fu,p,k,gk+valu(qp)}(pq)f_{u, p, k} = \max\{f'_{u, p, k}, g_{k} + val_u \cdot (q - p)\} (p \le q) \newline

[NFLS 1457/3] 文件复制 题解

大意

给定一棵树, 树上预先有两个节点被标记, 每个单位时间, 被标记的点可以标记一个相连的点. 求把整课树标记的最小时间.

题解

考虑 dp.

fuf_u 为将 uu 标记后, 还需多久将以 uu 为根的子树全部标记.

可以贪心处理: 设 aafv,vson(u)f_v, v \in son(u) 从大到小排序后的结果,

那么 fu=a1+1+a2+2+...f_u = a_1 + 1 + a_2 + 2 + ...

然后将将树看作如下形式:

1

然后二分最初的点中间的链断开的位置, 分别从两侧转移, 求最大值.

断开的边越靠右, 左侧节点的 fr1f_{r1} 越大, 右侧的 fr2f_{r2} 越小.

而最优方案一定是 fr2fr1|f_{r2} - f_{r1}| 最小, 故二分第一个使得 fr1>fr2f_{r1} > f_{r2} 的边即可.

[NFLS 1457/4] 破坏图 题解

大意

给定一个无向图, 有边权, 任意添加一条边, 使得任意删除一条边使得图不联通的代价最大.

题解

先跑一遍 Tarjan , 建出搜索树, 显然删除不是割边的边无法使图不联通, 故将它们的边权设为 \infty.

然后二分答案, 将边权比答案小的边的新边权设为 11 , 否则设为 00 (包括非割边) .

若要使答案成立, 必须找到一条路径, 使得覆盖所有的 11 边.

如下图, 这显然不能成立:

1

这个可以成立:

2

显然, 选择直径最优. 然后跑一遍直径, 检查是否等于 11 边的个数即可.

树上启发式合并

适用范围

树上的问题,对于一个节点,需要统计其的子树,且由于一些限制(主要是空间),无法直接合并多个直接子儿子的状态,只能 O(n2)\operatorname O (n^2) 统计,而 DSU on tree 可以优化至 O(nlogn)\operatorname O (n\cdot log n)

做法

  1. 树链剖分
  2. 递归处理轻儿子,并删除贡献
  3. 递归处理重儿子,并保留贡献
  4. 计算轻儿子的贡献

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void dfs(int u, int f) // 树链剖分
{
...
}

void dsu(int u, int save /* 是否保留贡献 */)
{
for (v <- edges(u))
if (!heavy_son(v)) dsu(v, false);
dsu(heavy_son(u), true);

for (v <- all_son(u))
if (v !in heavy_son(u)) add(v);

res(u) = res(u) + calc()

if (!save)
for (v <- all_son(u))
if (v !in heavy_son(u)) del(v);
}

莫队

适用范围

[l,r]O(1)[l,r+1],[l,r1],[l+1,r],[l1,r][l, r] \rightarrow_{\operatorname O(1)} [l, r+1], [l, r-1], [l+1, r], [l-1, r]

代码

1
2
3
4
5
6
7
8
9
10
11
12
sort(operations, (x, y) -> {
key1 = left_block(x), left_block(y);
key2 = right(x), right(y);
})

l = 1, r = 0;
for (o <- operations) {
while (l < o.l) del(l++);
while (l > o.l) add(--l);
while (r < o.r) add(++r);
while (r > o.r) del(r--);
}

复杂度

O(nn)\operatorname O (n \sqrt n)

最极端的情况

每次 rr 右移一位,ll 在一个块中,至多移动 n\sqrt n

[NFLS 1455/2] 动物园 题解

大意

定义 f(u,v)f(u, v) 为所有 uuvv 的路径上, 路径上点权的最小值的最大的路径的最大值.

u,v,uvf(u,v)n(n1)\frac {\sum_{u, v, u \not= v} f(u, v)}{n(n - 1)} .

题解

倒序按照点权加入, 用并查集维护连通性.

每次对于新联通的连通块,如 vv , 对于该点的答案贡献 valu(sizev(sizeusizev))val_u(size_v(size_u - size_v)) ,其中,uu 为当前讨论的点.

(解释: 即里面选一个, 外面选一个)

最后, 再加上 sizeold(u)(sizeusizeold(u))size_{old(u)}(size_u - size_{old(u)}) . (解释: 当前点旧的连通块向新的连通块连边)

技巧

讨论最大值, 最小值时, 可以枚举最大值或最小值, 然后每次讨论时忽略更大或者更小的点.

[NFLS 1454/4] 一九八四 题解

大意

给定一个无向图, 有若干询问,分两种.

  1. 不经过某条边 xyx \to yaa 是否能到达 bb ;
  2. 不经过某个点 xxaa 是否能到达 bb ;

题解

先跑一遍 TarjanTarjan , 建出 dfsdfs 树.

depx>depydep_x > dep_y .

询问一:

  1. xyx \to y 为非树边,可以到达;
  2. a,ba, b 都在或都不在 xx 的子树中,可以到达;
  3. xyx \to y 并不是割边,可以到达;
  4. 否则,无法到达;

1

询问二:

  1. aaxx 的子树中,将 aa 向上跳至 xx 的直接儿子,此时 xx 必须不是割点;
  2. yy 同理;
  3. 假如跳完后 aabb 为同一点,可以到达;

2

[NFLS 1451/3] 有向图++ 题解

大意

在有向图上, 有长度为 xx 的边, 对于每个询问,给定 s,ts, t, 求出当 xx 取不同正整数时, 最短路的值有多少种, 并且求出他们的和.

题解

对原图跑分层图最短路, 记 disu,idis_{u, i} 为从 ssuu , 恰好经过 ii 条长度为 xx 的边的最短路, 在求最短路时, 令 x0x \leftarrow 0.

可以得到若干条方程 yu=ix+dist,iy_u = ix + dis_{t, i}, 枚举考虑最短路经过 ii 条长度为 xx 的边的情况, 联立所有方程, 可以得到 (设 fi=disu,if_i = dis_{u, i})

x<fjfiij,i>jxfjfiij,j<ix \lt \frac {f_j - f_i} {i - j}, i > j \newline x \ge \frac {f_j - f_i} {i - j}, j < i \newline

然后可以求出 xx 的取值范围, 对答案的贡献即为

cntcnt+hiiloi+1cnt \leftarrow cnt + hi_i - lo_i + 1 \newline

resres+i(hii+loi)(hiiloi+1)2+dist,i(hiiloi+1)res \leftarrow res + i \frac {(hi_i + lo_i)(hi_i - lo_i +1)} 2 + dis_{t, i}(hi_i - lo_i + 1) \newline

(注: 不等式中, 不能两边都取等, 否则整数值会被重复考虑. )