D
三分 & 反悔贪心
计算最大匹配数很简单,难点在于计算每种匹配数情况贡献的最大值。
贪心地想也能发现,对于每个集合,若固定选择线段的个数 \(cnt\),最大贡献为:
这个可以用前缀和预处理出来,以做到对于某个给定匹配数,能够\(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
组合计数
需要将式子拆开,即计算:
考虑将上面的三项拆开来计算:
- 对于 \(2 \times min(dep[u], dep[v])\) 这一项:钦定 \(dep[u]\) 较小,对于 \(u\),计算符合要求的 \(v\) 的数量。则 \(v\) 需要满足:\(dep[v]>=dep[u]\) 且 \(v\) 不在 \(u\) 的子树内。可以按深度预处理结点数量的后缀和 \(depsuf\),则数量为:\(depsuf[dep[u]]-siz[u]\),贡献为:
- 对于 \(2 \times dep[lca(u,v)]\) 这一项:计算每个点 \(a\) 作为 \(lca(u,v)\) 时的 \((u, v)\) 数量即可。显然为:
最后还需要除以2,因为 \((u,v)\) 和 \((v,u)\) 都计算了一次。
- 对于 \(-1\),直接计算 \(good pair\) 的数量即可:
分别计算以上三项并求和,即为答案。
code