博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[CF 468 Div.1D]Valid Sets
阅读量:5738 次
发布时间:2019-06-18

本文共 987 字,大约阅读时间需要 3 分钟。

题意

一个\(n\)个节点的树,边有边权,求一个字典序最小的排列\(p\),令\(\sum_{i=1}^n\limits dis(i,p_i)\)最大

分析

我们考虑\(dis(i,p_i)\)实际上可以拆成三段:\(\sum dep(i)+dep(p_i)-2dep_{lca(i,p_i)}=2\sum dep_i-2\sum dep_{lca(i,p_i)}\)

考虑选重心作为根,那么就可以平衡地配对起来,让不同子树之间的配对,使得后面那一项变成\(0\),那么整个式子就最大。那么这时这个答案就很容算出来,但是怎么让字典序最小呢?

考虑我们把root删掉的话,那么我们要最小就需要满足两个需求:

  • 每次给某个\(i\)\(p_i\)选一个最小的\(j\),同时这个\(j\)还不能在和\(i\)同一棵子树里面
  • 不能在某个时刻对于某个\(i\)我们不能选点匹配了,也就是我们对于某些子树我们可能需要优先考虑,这时需要优先满足贡献最大的需求

先考虑“合法解”满足的条件。什么时候我们需要优先考虑某些子树呢?我们考虑目前已经确定了排列的前\(i\)项,一个子树里面有\(t\)个大于\(i\)的节点(肯定都没配对),这个子树里面还有\(x\)个没被配对的节点(没被前面的某个\(p\)选中),那么实际配对节点一共有\(n-i\)个,但是不能配对同一棵子树里面的,所以实际可以配对的只有\(n-i-x\)个,还未配对的\(t\)个节点必须有配对。

所以当\(t+x\leq n-i\)的时候才行。然而如果一棵子树出现\(t+x=n-i\)的时候就很关键了。因为\(i\)在一直变大,右边一直在变小,如果左边不能一起变小的话就完蛋了。那么要么就是\(t\)要么就是\(x\)能够减\(1\),那么这个等式其实就会一直满足了!

我们考虑用set维护下所有子树的\(t+x\),然后考虑有没有满足等式的子树,然后如果有,而且如果\(i\)在这棵子树里就照做,反之必须要找一个\(j\)在这棵子树里。剩下的情况上面已经讨论过了。

对于找最小的贪心,可以用线段树,同一棵子树里面按照编号放进一个区间里面,每次指针往后移即可,而对于根可以和任意节点(包括自己)配对,需要特殊考虑。

转载于:https://www.cnblogs.com/wendavid/p/9101999.html

你可能感兴趣的文章
Okio源码分析
查看>>
vue.js一个简单例子的基础说明系列-[第4个例子]-----这个例子.我还是不明白
查看>>
Java内存区域
查看>>
Android Material Design 阴影实现
查看>>
Velocity 简明教程
查看>>
OpenCV (iOS)中的形态学变换(11)
查看>>
git
查看>>
python版亲戚关系计算器
查看>>
极限编程 (Extreme Programming) - 迭代计划 (Iterative Planning)
查看>>
环境变量python从版本2.x更改为3.x时,yum报错
查看>>
angular 拦截器
查看>>
什么软件可以将图片制作成GIF
查看>>
微服务的4个设计原则和19个解决方案
查看>>
PAT A1029
查看>>
985-查询后的偶数和
查看>>
小程序瀑布流效果,解决左右两边高度差距过大的问题
查看>>
js ES6 求数组的交集,并集,还有差集
查看>>
图片懒加载通俗易懂
查看>>
MQ框架的比较
查看>>
JS核心知识点梳理——数据篇
查看>>