[夏令营机试题]T校机试题 积木 二分+线段树 (思想)

题目描述:一摞积木(1e5),每个长宽都是1*1,高h,密度ρ,由题目输入。每块积木承重a,由题目输入(超重不会塌)。现在我从第一块开始一块一块的堆积木,问堆到第几块的时候超重体积超过V,V由题目输入。

首先,所有积木的超重体积随着积木的增多是单调递增的。因此可以用二分记录它在放上哪块积木时超重,然后用一个数组add记录放上某块积木时新增的超重部分的体积,求前缀和就是放上第i块后超重部分的总体积,最后二分查找一下V就可以了。当然题目是多组询问,也可以给询问排序后遍历一遍取得所有答案。

 

但是这里有个很大的问题,就是积木可能是有一部分超重,一部分没超重,不能看做一个整体。可以说在放上第i块积木时有一部分超重了,但是没有全超重,然后可能在放上第i+1块,第i+2块,...,第j块超重部分一直在增加,直到第j块放上整个积木完全超重体积不再增加。

任意时刻,F(下表面)= F(上表面) + G0(自重)。我可以二分一下每块积木的上下表面超重时分别是第几块,得到一个变换区间(i, j)。

 

在(i,j)变换区间内有一个有趣的问题,就是放上第k块积木时超重体积增加了多少呢。

假如一块积木S,在变换区间内的某时刻的超重临界点在P点,称重Fp。那么放上积木k的时候,Fp' = Fp + G(k)。因此积木平衡点将上移直到抵消这个G(k),而抵消是通过减少上方自重,因此从原来的临界点P到新的临界点P',减少的积木重量为G(k),即是新增超重部分的重量G(k)。则新增体积为V(s, k) = G(k) / ρ(s)。

值得一提的是边界i和j需要单独计算一下新增的超重部分体积,这个最后处理。i,j开区间内直接处理即可。

 

现在我定义一个公式A(s, k) = V(s, k) / G(k) = 1/ρ(s)。

我们需要分别求放上某块积木k的时候,其下方所有积木增加的重量,于是对于每一个在变换区间的积木x1, x2, ..., xn,体积增加都是V(xi, k)。定义∑V(k)  = G(k) * ∑A(k)。

对于每块积木来说,在它变换区间范围内的点,虽然V不一定相同,但是A都是相同的1/ρ(s)。

因此可以给数组A构造一个线段树,初始化为0,对于每块积木s的变换区间(共n个)进行一次区间更新,给所有数加上1/ρ(s),复杂度O(nlogn),然后更新完依次取得每个点的最终值,复杂度O(nlogn)。

然后给每个点的最终值*G(k),加到add上,将n个区间的边界分别加到add上,O(n)。

 

最后还是可以通过add的前缀数组处理多组询问的答案。

代码:不会写=w=。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值