CF div2 1000(DE)

D

三分 & 反悔贪心

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

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

i=1cnta[n+1i]a[i]

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

对于某个匹配数 i,可以暴力枚举选取集合 a 的线段数 x ,则选取 b 的线段数为 ix。枚举 x[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

组合计数

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

goodpair(u,v)2×min(dep[u],dep[v])2×dep[lca(u,v)]1

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

  1. 对于 2×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])×dep[u]

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

((siz[a]1)2v=son[a]siz[v]2)×dep[a]

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

  1. 对于 1,直接计算 goodpair 的数量即可:

n×(n1)/2u(dep[u]+siz[u]1)

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

code

posted @   jxs123  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示
主题色彩