加载中...

CF div2 1000(DE)

D

三分 & 反悔贪心

计算最大匹配数很简单,难点在于计算每种匹配数情况贡献的最大值。

贪心地想也能发现,对于每个集合,若固定选择线段的个数 \(cnt\),最大贡献为:

\[\sum_{i=1}^{cnt}a[n + 1 - i] - a[i] \]

这个可以用前缀和预处理出来,以做到对于某个给定匹配数,能够\(O(1)\)计算答案。

对于某个匹配数 \(i\),可以暴力枚举选取集合 \(a\) 的线段数 \(x\) ,则选取 \(b\) 的线段数为 \(i-x\)。枚举 \(x \in [0,i]\) ,并选择最大值 \(mx\) 即为答案。但这样做太暴力了。考虑 \(mx\) 关于 \(x\) 是否具有单调性或单峰性,以优化暴力:

观察上面的前缀和,可以发现,前缀和维护的序列一定是单调递减的。这样就发现了可优化的关键点——设在 \(a\) 中选 \(x\) 对线段的贡献为 \(w\),若在 \(a\) 中多选一个线段,则由于总线段数固定,在 \(b\) 中就要少选一对线段,\(a\) 数组会使 \(mx\) 增大,\(b\) 数组会使 \(mx\) 减小。而随着选择 \(a\) 中线段继续增多,\(a\) 数组会使 \(mx\) 继续增大,但增加的贡献与之前相比减少了,同理 \(b\) 数组减少的贡献与之前相比会增加。因此总贡献的变化是呈山峰形的,可以三分处理每种情况的答案。

code1

本题还有反悔贪心解法:若两个集合中都可以挑选线段(\(free\)点数均\(>=2\)),则贪心选对当前贡献最大的即可;若只能选一个,则选这一个;若都不能选出线段(某一个集合\(free\)点数为0,或者两个集合\(free\)点数均为1),则需要撤销一条不能选择线段的集合中的线段,并新添加另一个集合的两条线段。由于已经处理出了正确的\(kmax\),因此可保证一定能做到这一点,直接模拟上述过程即可。

code2

E

组合计数

需要将式子拆开,即计算:

\[\sum_{为good pair的(u,v)}2 \times min(dep[u], dep[v]) - 2 \times dep[lca(u,v)] - 1 \]

考虑将上面的三项拆开来计算:

  1. 对于 \(2 \times min(dep[u], dep[v])\) 这一项:钦定 \(dep[u]\) 较小,对于 \(u\),计算符合要求的 \(v\) 的数量。则 \(v\) 需要满足:\(dep[v]>=dep[u]\)\(v\) 不在 \(u\) 的子树内。可以按深度预处理结点数量的后缀和 \(depsuf\),则数量为:\(depsuf[dep[u]]-siz[u]\),贡献为:

\[(depsuf[dep[u]]-siz[u]) \times dep[u] \]

  1. 对于 \(2 \times dep[lca(u,v)]\) 这一项:计算每个点 \(a\) 作为 \(lca(u,v)\) 时的 \((u, v)\) 数量即可。显然为:

\[((siz[a] - 1)^{2} - \sum_{v=son[a]}siz[v]^{2})\times dep[a] \]

最后还需要除以2,因为 \((u,v)\)\((v,u)\) 都计算了一次。

  1. 对于 \(-1\),直接计算 \(good pair\) 的数量即可:

\[n \times (n - 1) / 2 - \sum_{u}(dep[u]+siz[u]-1) \]

分别计算以上三项并求和,即为答案。

code

posted @ 2025-02-19 15:26  jxs123  阅读(12)  评论(0)    收藏  举报