CF2051E 题解
CF2051E 题解
赛时D +7 卡一个多小时,E读错半小时题,比赛完了才发现。估计是今年干出来的最抽象的事情之一。
实际上时间足够也不一定能够在场上做出来E,我感觉这是一道很妙的转化。
题意
每个人有 \([a_i,b_i]\) 的一个价格,如果商品价格在 \([1,a_i]\) ,则这个人会购买并且留下好评;如果价格在 \((a_i,b_i]\) ,则会购买并且留下差评;其他情形下不会购买。
现在给定一个 \(k\) ,最多收到 \(k\) 个差评的情况下,制定一个对每个人都一样的价格,使得最后的收益最大。
分析
很显然是不具有单调性的,所以二分价格或者是差评人数之类的是行不通的。
转化1
要明确的两点是:
1.如果最后一个价格没有被任何区间包含,那完全可以把它提高到离他最近的一个 \(a_i\) ,这样差评不会增加,并且答案是这个差评数下可能的最大值。
2.如果说有一个价格被包含了,不在 \(a\) 上,但是不与任何一个 \(b_i\) 重合,倘若这种情况下给出差评的人不超过 \(k\),那么完全可以把这个价格提高到最近的 \(b_i\) ,这样给差评的人也不会增加,并且可能是最大的答案。
所以综上所述,最优答案的价格仅可能在端点处取,只用枚举每个端点就可以了。
转化2
对于每个价格,又该怎么计算会购买的人数,和会给差评的人数?
会购买的人数很好计算,就是满足 \(b_i\ge price\) 的人数。
给差评的人数可以抽象成如下问题,给出坐标轴上一个点,问在若干条线段里,有多少条包含了该点,如下图。
在所有会购买,也就是右端点在红线之后的线段中(记有 \(nums\) 条),不会给出差评的,其实就是所有左端点在红线之后的线段条数(记为 \(good\) ),他们的右端点也一定在红线之后,所以包含在了 \(nums\) 中。很显然地就可以算出给出差评的人数 \(bad=nums-good\) 。
这一个过程可以直接分别对于 \(a,b\) 数组进行排序,不用维护顺序,然后二分查找即可。
本文来自博客园,作者:Hanggoash,转载请注明原文链接:https://www.cnblogs.com/Hanggoash/p/18623210