做题笔记
P6155修改 贪心
注意到性质:修改的个数越少越好。当我们需要使 \(a_i\) 与序列中其他数不同时,即使选择“修改 多个非 \(a_i\) 的数 ”与“ 只 修改 \(a_i\) ”所需要的修改次数相等,但是由于我们可以把最小的 \(b_i\) 分配给 \(a_i\),而修改不同的数需要用到不同的 \(b_i\),且这些 \(b_i\) 不会小于最小的 \(b_i\),我们可以判断:只修改一个数的代价最优 。
思路:找到每个 \(a_i\) 修改后的值,计算所需的修改次数。我们需要让修改的数的个数最少,并将修改次数最多的数分配最小的 \(b_i\)。
在实现中,我们需要让 \(a_i\) 从大到小 排序。这样可以让修改的数的个数更少,正确性显然。
P4447分组 贪心
要求最小值最大,考虑二分答案。
数组 \(q_i\) 的意义是在第 \(i\) 组中如果想要再放一个数,这个数应该是多少。数组 \(siz_i\) 的意义是第 \(i\) 组有多少个人。
我们在 \(q\) 中寻找可以放下 \(a_i\) 的 \(q_{pos}\), 当找到第一个满足要求的 \(q_{pos}\) 之后,接着尝试往后找满足要求的 \(q_{pos + 1}\)。因为越靠后的 \(q\) 越晚被建立,故其存储的答案会更小。我们将当前 \(a_i\) 累加到尽量小的 \(q\),可以尽量满足最小值最大的题意。
接下来,如果可以在当前的 \(q_{pos}\) 中放下 \(a_i\) 那么就放。并且把 \(q_{pos}\) 和 \(siz_{pos}\) 分别加1;如果不行,那么需要新建一个 \(q_{cnt + 1}\) 来存放这个人。 \(q_{cnt + 1} = a_i + 1\),\(siz_{cnt}\) 设为1。
最后答案为 \(\min_{1 \le i \le cnt}\{siz_i\}\)。
P11268买东西题 反悔贪心
反悔贪心。
将优惠券按照 \(w_i\) 升序排序,将物品按照 \(a_i\) 升序排序。
令 \(j < i\),且 \(j\) 使用优惠券 \(v_j\)。
-
对于 \(j\):
- 使用优惠券。花费 \(a_j\) - \(v_j\)。
-
对于 \(i\):
- 使用折扣价。花费 \(b_i\)。
- 使用不同于 \(v_j\) 的优惠券。花费 \(a_i - v_i\)。
- 抢走 \(j\) 的优惠券:
- 即 \(i\) 的花费为 \(a_i - v_j\),而 \(j\) 的花费变成 \(b_j\)。
- 此时 \(i\) 与 \(j\) 的总花费变化为:\((a_i - v_j) - (a_j - v_j) + (b_j) = a_i - (a_j - b_j)\)。我们发现这个操作事实上等价于对 \(i\) 使用了一张 \(a_j - b_j\) 的优惠券。
我们使用 priority_queue 来维护。
- 对于每个物品 \(i\),我们将它能使用的优惠券压入优先队列中,并对 \(i\) 进行决策:
- 如果使用折扣价更加优惠,直接使用折扣价;
- 如果使用优惠券更加优惠,使用优惠券。弹出使用过的优惠券并压入一个新的价值为 \(a_i - b_i\) 的优惠券,以便后续的物品需要抢夺 \(i\) 的优惠券(如果需要)。
每个元素仅被压入和弹出一次,时间复杂度为 \(O(n\log n)\)。
P2882 [USACO07MAR] Face The Right Way G
区间翻转(异或)的 \(O(1)\) 差分实现。

浙公网安备 33010602011771号