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,就是利用数组的值去存储时间而不是某一维度去存储时间,因为时间太大了)
方程很好推,也很好优化,就不推了