出题&题解4

由于3比较水略过

Task1:其实是HDU5265,很久以前某BC皮球出的题

这个你只要对所有 vi P 取模,然后排个序,再枚举每个点,按照Pvi在数组上二分即可。有个坑就是二分到的可能是自己,造数据的时候特意卡了一下,不跳的就只有40分。

Task2:其实是BZOJ4033,一道简单的树形dp

这个你只要考虑每条边在答案里的贡献即可,枚举 v 子树to里黑点的个数 w ,然后这条边的贡献就是(kw)wval(v,to),白点贡献同理。
所以是一个类似分组背包的东西咯,看起来复杂度像是 O(nk2) ,其实在dp的时候注意一点,在合并状态的时候第一个for只for到目前的 sz[v] (即 to 左边的子树),即可保证复杂度是 O(n2)

关于证明:你可以把转移时两层for视为for两个子树里的节点(for size和for 节点次数相同所以可以这么考虑),那么关于节点 u 和节点v,只有在 lca(u,v) 的地方才会被考虑到转移,所以复杂度是 O(n2)

Task3:其实是BZOJ2667,一道不太难的贪心。

题解之前写过,不过有些不详细,但是有代码,所以可以见这个传送门

首先 n 那么小除了暴力枚举相信你也不知道可以干什么。。

枚举得到那些订单,那么收益那一维可以丢掉了。

现在问题变成了如何在O(n2)的复杂度里check一些订单是否成立。
先按时间排个序。

然后我们可以转化一下问题,订单 q 变成(tq,aq=qi=1gi)
这样问题可以简化为对于每个订单 q ,是否满足在时间tq时,有一种决策可以使得生产商品的总数到达 aq 个。

接下来我们用两次贪心和一个公式解决这个问题。

第一个很显然的贪心:在一段时间 t 里,如果你要选择x天进行提高产率,那么让产率最大化的方案显然是在 t 天里前x天进行提高产率,后面的时间进行生产。

想到这里,并且看到我切分 n=1 的那部分,相信你已经想到如何解决这个问题了:可以用一元二次不等式解决这个问题。

考虑 n=1 的时候,选 x 天提高产率,剩下tx天进行生产,产量为 (1+x)(tx) ,这里的 1 是最初的产率,我们可以用s带掉他,那么产量即为 (s+x)(tx)
展开这个方程,你会发现它是开口向下的一元二次方程。结合check的时候,有一个要求 a ,我们就得到了一个一元二次不等式。直接用求根公式解掉它(大家数学都很好不用我说吧),别忘了判定Δ>=0

那么 n=1 的情况都解了, n1 的情况自然轻松又愉快了,不就是联立一些不等式嘛,小学生都会的事开玩笑嘿嘿嘿

现在你有很多的由一元二次不等式解出来的简单不等式 x[li,ri] ,你该如何选择?或者说这些区间可能并不完全包含,区间 i 右端点会小于区间j的左端点。

那么我们可以这样想,你并不是只在一个区间里提升产率,相反的,你有 n 个区间可以提升产率,如果当前的x小于未来的某个 li ,不要紧,以后还有时间弥补,但是如果 x 已经大于某个ri了,那么不用多说,已经废了。。

所以第二个贪心水落石出了。我们每次按顺序扫描一下这些区间,贪心地取 x=minnj=iri ,从数学的角度说这个值无疑可以在满足所有右端点的情况下满足所取的值 x 最靠近(如果有的话)左端点大于x,日后的决策可以更加轻松。意识流的看也没用错,当前产率很高,虽然总产量不咋地,但是在满足扫描过的区间的情况下,日后的发展基础更好了是不?(注意这个东西已经满足了右端点的约束,所以已经满足了前 i 个区间的成立以及后面的区间成立的可能性)

接下来的事情不用我说了,每次按如上决策砍掉一个订单(即在商品总量里去掉gi),然后进行相同操作。不知你有没有注意到最开始我用 s 替换掉了最初的生产力1,就是为这里服务的,你只要把提高的产率加到 s 里,后面的步骤可以说不变。(不过要注意后面所有的a会相应地减少)

那么,这道BZOJ上不超过100人的题,解了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值