题目大意
给定一个长度为\(n\)由\(0,1\)组成的序列。然后进行\(n\)次操作,第\(i\)次操作会把前\(i\)个数升序排序。
比如\(0,1,0,1\),\(4\)次操作形成的序列分别是\([0,1,0,1],[0,1,0,1],[0,0,1,1],[0,0,1,1]\),然后每一位分别相加为\([0,2,2,4]\),设此数组为\(c\)。
现在给定数组\(c\),求原来的数组。\(1 \le n \le 2*10^5\),且保证有解 题目链接
思路
我们首先来计算有多少个\(1\),每个排序数组\(1\)的个数不会变,所以我们直接拿\(c\)数组之和除以\(n\)即可,设为\(num\)。
可以考虑从\(c\)最后一个位置计算: * 如果\(c[n] = n\),那么就说明\(a[n] = 1\),且这个\(1\)不会对前面的答案产生影响。 * 如果\(c[n] = 1\),那么就说明,最后一次排序时,把一个\(1\)移动到了此位置。所以\(a[n] = 0\)。
且我们可以发现,最后一次排序后,数组一定是形如\(0,0,0,0,1,1,1,1\)的形式,而\(1\)的数量我们已经算出,所以我们可以直接把数组\(c\)减去这个序列,这样我们就得到了\(n-1\)次排序后的\(c\)数组。且这相当于一个子问题,可以按照上述的方法继续求解。
需要注意的是,如果我们算出当前位置是\(0\),那么前面的数中,\(1\)的个数需要减一,否则数量不变。
由于直接暴力相减\(c\)数组会超时,我们可以提前预处理出每个位置要减去的数,我们利用\(b[i] - i\)来表示,
代码
1 |
|
- 本文作者: 水蓝络合物
- 本文链接: https://miku39393939.github.io/2022/05/13/cf1659D/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!