牛客寒假基础算法训练营5(GH)

G

树状数组 + 树上启发式合并

考虑计算所有点作为 z 时的贡献,最后加和。

相当于所有包含 z 的路径 (x,y),其中满足:wx=wywz>wx,设现在要计算点 u 作为 z 的答案:将整个树分成 以 u 为根的子树 和 之外。则贡献有两种:

  1. x 在子树内,y 在子树外
  2. x,y 均在子树内

快速计算所有子树中每种权值大小的个数,显然是树上启发式合并。现在考虑如何利用这个信息计算贡献:

情况1很简单:先统计出每种权值的总数 sum[w],则设子树内有 cnt[w]个,子树外就有 sum[w]cnt[w] 个。计算子树 u 中情况1的贡献,即计算:

w<w[u]cnt[w]×(sum[w]cnt[w])

统计的是前缀信息,则先将权值离散化,再用一个树状数组实时维护 每种权值 上面的式子即可。

对于情况2,熟悉套路的话很快就能看出来贡献可以用 子树大小和的平方 子树大小平方的和来算。其中前者只需要知道子树内某种权值的数量;而直接计算某个子树中 每个子树分支的某种权值个数的平方再加和 是个难点。

但可以将思维转化一下:可以直接看以 u 为根的子树内权值 <
u 的父亲权值的点的个数,对所有这样的子树作统计即可。计算这个和上面的方法是相同的。

注意情况2最后算出来要除以 2,因为 (u,v)(v,u) 重复计算了。具体细节见代码。

code

H

n<=3000,因此直接考虑任意一个子区间可以在多少种分割方法中出现即可。用ST表维护区间最大值和最小值,然后用隔板法计算分割方法数。

code

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