题意
有$n(1\leq n\leq 10^5)$个盒子,每个盒子有$a_i(0\leq a_i \leq 1)$个糖果,你每一次可以将第$i$个盒子里的糖果放到第$i-1$或$i+1$个盒子中(如果盒子存在)。最后要使每个盒子的糖果数量都整除$k(k>1)$(注意盒子可以为空),问最小操作数。
分析
$(1)$因为糖果是类似于平铺的形式,堆叠时,我们可以发现所有存在糖果的盒子中数量均为$k$。若存在一个盒子中有$2*k$个糖果,在平铺到堆叠的过程中,将另外$k$个糖果分在更近的盒子能得到更小的答案。
$(2)$设糖果总数为$cnt$,所有存在糖果的盒子数量均为$k$,我们又可以发现,最小的操作是将$1$~$k$、$k+1$~$2k$、……、$ik+1$~$(i+1)*k$放在一起,即将相邻的$k$个放在一堆。
$(3)$对于某$k$个糖果,需要找到一个盒子,这个盒子到这$k$个糖果的距离最小(kNN算法)。我们将糖果看成数轴上的点,运用高一的绝对值知识(我忘了,我向高中数学老师谢罪)。
- 若$k$为奇数,则将该盒子设置为最中间糖果所在的盒子
- 若$k$为偶数,则将该盒子设置为最中间两个糖果中任意一个所在的盒子
即对于$ik+1$~$(i+1)*k$来说,第$k-i/2$个盒子,设其坐标为$ave$。
$(4)$为降低时间复杂度,我们采取前缀的思想,$sum[i]$表示坐标$i$之前的糖果的坐标总和(没糖果的盒子不加),$num[i]$表示坐标$i$之前有多少糖果。
$(5)$枚举可以被$cnt$整除的$k$,模拟$(2)$的过程,设$first$为第$ ik+1$个糖果的坐标,$last$为第$(i+1)k$个糖果的坐标,那么每个循环都得加上$(num[ave] - num[first - 1])*ave-(sum[ave] - sum[first - 1])+(sum[last] - sum[ave])-(num[last] - num[ave])ave$,意思为$ave$之前的操作次数加上$ave$之后的操作次数,最后取最小值
$(6)$记得开$long\ long$,$INF$也记得开大一点。
1 |
|