「小组联考」最优卡组
题目
题目描述
输入格式
输出格式
样例
2 9 3 1 3 5 3 2 3 3
8 8 7 6 6 5 4 4 3
样例解释
数据范围与提示
![](https://img2018.cnblogs.com/blog/1731121/201910/1731121-20191023182531944-933379373.png)
题解
做题经历
考试的时候想到一个很类似于正解的东西,预估时间复杂度 $O(nk)$ ,但是想到很多限制,结果代码都不敢码......
最后痛失 $50pts$ 。
接下来说一下这个思路吧。
$SUBSULOTION#50pts$
首先,我们先将每个卡组内的卡从大到小排个序。
然后,我们再定义一个数字串,定义不方便说,直接拿例子解释
有这样一个数字串:
数位: $12345$
数串: $13211$
这个数串表示的意思就是:在这种情况下,第一组取的是第一大的,第二组取的是第三大的,第三组取的是第二大的......以此类推
那么,毫无疑问,最大的能力值一定是 $11111$
然后呢?次大的呢?
我们不知道次大的是哪个,但是我们肯定可以保证次大在 $21111、12111、11211、11121、11112$ 中
我们把这些数串叫做子状态
那么这个思路就出来了:
把状态放进优先队列里面,每次取出最大的状态,输出,再放进它的子状态......重复 $n$ 次即可。
但是这样呢,每个状态会最多被放入 $k$ 次,为什么?
举个栗子:
状态 $23426$
它可能被 $13426、22426、23326、23416、23425$ 放进去。
那么时间复杂度大概是 $O(n\cdot k\cdot log)$
看看范围,还可以过一半,挺好......
正解
一道思路诡异的贪心题,但是这个思路也不是不可想,只是要分析到点上。
我们其实可以在 $50pts$ 的思路上加以改进。
首先,超时思路为什么会时间复杂度高?
是因为同一个状态被最多放进了 $k$ 次。
那么怎么解决这个问题呢?
这里有一个最终的解决方法,先说出来,然后解释其正确性以及如何思考。
首先,我们可以在输入的时候得到 $k$ 个串 $a_{i,j}$ 表示第 $i$ 组卡牌的能力值
将每个组内卡牌从大到小排序,然后设 $val_i=a_{i,1}-a_{i,2}$
具体意思就是 $val_i$ 表示第 $i$ 组中最大的牌减次大的牌的值
再按照 $val_i$ 从大到小把数组顺序重排
在处理完这些之后,我们来看怎么放进状态的子状态
设我们有一个状态 $\overline{×××...××××ab11111......11111}$
其中 $×$ 不用管,就是来占位置用的,而 $b$ 之前全是 $1$
那么我们会对这个状态做出三个转移,其中一个是特例:
- 子状态一:$\overline{×××...××××a(b+1)11111......11111}$
- 子状态二:$\overline{×××...××××ab21111......11111}$
- 子状态三(仅当 $b=2$ 时):$\overline{×××...××××a(b-1)21111......11111}=\overline{×××...××××a121111......11111}$
最后把他们放入优先队列,同样地维护即可。
那么这样做有什么好处吗?
首先,它不会出现重复状态被压入优先队列。
为什么?
假设队列中有这样一个状态:$\overline{×××...××××ab11111......11111}$(注意不要和之前的状态混淆了)
如果 $b≥2$ 且当 $b=2$ 时 $a≠1$ ,那么它只有一个前驱 $\overline{×××...××××a(b-1)11111......11111}=\overline{×××...××××a111111......11111}$
但是如果 $b=2$ 且 $a=1$ 时,我们可以否决其前驱是 $\overline{×××...××××a(b-1)11111......11111}=\overline{×××...××××1111111......11111}$ ,这个很好想
那么它的祖先就有且只有 $\overline{×××...××××1211111......11111}$ ,就是那种特殊子状态
所以说,这样转移显然每种状态就只会出现一次
那么,它还有什么优势呢?
又来举同一个栗子,我们有状态 $\overline{×××...××××ab11111......11111}$
那么,当不是特殊情况时,我们的转移是 $\overline{×××...××××(a+1)b11111......11111}$ 或者是 $\overline{×××...××××a(b+1)11111......11111}$
那么,这两种状态。是否都比 $\overline{×××...××××(a+1)b11111......11111}$ 小呢?答案是肯定的。
但如果是特殊情况:$\overline{×××...××××2111111......11111}\Rightarrow \overline{×××...××××1211111......11111}$
这样转移的话,子状态是否也是比前驱状态小呢?
答案也是肯定的。
为什么?提示:这和我们开始时那个特别的排序也是有关的。
综上,这个处理方案有两点好处:
- 状态唯一
- 子状态大小有序
那么我们看一看,其时间复杂度是不会超过 $O(3nlog)$ 的。
但是又有一个问题:这个神仙思路是怎么想到的呢?
$AC$ 思路就是这样,代码:
题解都打了那么多,代码却写不出来了......