Messenger in MAC

首先来看看官方解答

当确定了一个选出的数之后,我们\(a\)的和肯定就定了,我们肯定要将\(b\)的和变得最小是最优的,很容易想到的一个策略就是将\(b\)从小到大排序,然后\(b\)的和就等于\(b_{max}-b_{min}\)

这其实是正确的。官方解答没有给出证明,我来证明一下。首先将\(b\)看做数轴上的点,比如下图

然后这种做法就相当于\(b_i\)\(b_{i-1}\)这一段距离被覆盖而且刚好被覆盖一次

我们考虑其他的任何一种排法,肯定是不存在\(b_i\)\(b_{i-1}\)这一段距离没有被覆盖的,因为你不可能分成两个不连通的块

所以最开始的排法既是下界又可以达到,当然就是最优的

于是我们枚举\(b_l\)\(b_r\),此时有

所以当我们固定了一个\(r\)之后,我们指针向前面走,实时维护一个\(set\)或优先队列,用一个变量记录里面所有元素的和,注意到\(b_l\)是在递减的,所以当我们加入一个新的\(a\)之后,如果超出\(l\)了,我们直接弹出最大值就好了

然后再来看看我的做法,当然仍然是按照\(b\)排序先,然后利用动态规划,设\(f[i][j][0/1]\)表示前\(i\)个数,选出了\(j\)个数,第\(i\)个数是否选择的最小时间(注意这里利用一个经典trick,就是利用数组的值去存储时间而不是某一维度去存储时间,因为时间太大了)

方程很好推,也很好优化,就不推了

posted @ 2024-03-06 22:20  最爱丁珰  阅读(4)  评论(0编辑  收藏  举报