[AGC023F] 01 on Tree

大概是NOIP前最后一场模拟赛了,yj组织的信心赛。

link


题目大意:

  • 给出一棵 n n n 个节点的树,以及一个空序列。
  • 每个节点上有一个取值在 { 0 , 1 } \{0, 1\} {0,1} 中的数。
  • 每次你可以选择没有父亲节点的点删除,并且将这个节点上的数字放在当前数列末尾。
  • 请你求出这个数列可能得到的最小逆序对数。
  • n ≤ 2 × 1 0 5 n \leq 2 \times 10^5 n2×105

难点在于贪心策略基于整棵树,而不能只通过独立点的子树合并。

很久没做过类似的贪心了,思想很经典,用Exchange Argument的方法来构造正确的贪心策略。在我的理解层面上是先进行假设,通过假设某策略更优,接着得到该策略更优所需具备的条件,最终将贪心策略用权值大小来表示。

题解:题目要求逆序对数最小,首先想到尽量让最终得到接近00...01...11的数列。发现当父节点进行扩展时,先选 v a l val val 为 0 的子节点一定不劣。所以可以先将 v a l val val 为 0 的节点与其父亲合并再进行贪心。
基于这一想法,可以考虑节点与父亲合并。由于父节点一定在子树前面入队,所以父与子的逆序对数恒定,那么只需考虑子树间合并的先后关系。

这时候就要用到Exchange Argument的思想了,可以发现在原先合并的基础上,(合并后)每个节点都代表了若干 v a l = 0 val=0 val=0 的点和若干 v a l = 1 val=1 val=1 的点。考虑此时对于子树 i , j i,j i,j 合并的先后顺序,若先拓展 i i i 再拓展 j j j,则新增的逆序对数为 c n t 1 i × c n t 0 j cnt_1i\times cnt_0j cnt1i×cnt0j,其中 c n t 0 / 1 x cnt_{0/1} x cnt0/1x 表示节点 x x x 代表 c n t 0 / 1 cnt_{0/1} cnt0/1 的 0/1。同理,若先拓展 i i i 再拓展 j j j,则新增的逆序对数为 c n t 1 j × c n t 0 i cnt_1j\times cnt_0i cnt1j×cnt0i。显然,假设先拓展 i i i 比先拓展 j j j,则应满足 c n t 1 i × c n t 0 j < c n t 1 j × c n t 0 i cnt_1i\times cnt_0j<cnt_1j\times cnt_0i cnt1i×cnt0j<cnt1j×cnt0i,即 c n t 1 i c n t 0 i < c n t 1 j c n t 0 j \large\frac{cnt1_i}{cnt_0i}<\frac{cnt_1j}{cnt_0j} cnt0icnt1i<cnt0jcnt1j。所以只需将每个点的 c n t 1 i c n t 0 i \large\frac{cnt_1i}{cnt_0i} cnt0icnt1i 放进优先队列,依次合并即可。

注意到分母可能为0,此时其所代表的权值为 + ∞ +\infin +,直接将其赋值为 + ∞ +\infin + 就行。
对答案的贡献可以在合并时完成。


这题最重要的点是Exchange Argument构造贪心策略的方法,比如对于一道单纯靠子树合并难以完成的题目(像这题,拓展的过程长得像bfs的),可以尝试假设 a a a b b b 优相应需要的条件,后将贪心策略转化为单纯的权值比较、合并,可以解决部分普通贪心不好解决的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值