Codeforces Round 920 Div 3
A - Square
直接记录最左最右、最上最下即可。
1 | // Problem: A. Square |
B - Arranging Cats
先算需要转换多少个0/1使得1的数量相等,转化完剩下的不同数对个数除以2即为接下来需要移动的最小次数。二者相加得到答案。
1 | // Problem: B. Arranging Cats |
C - Sending Messages
简单dp。
设dp[i]
表示发出第i条信息后的最小耗电量。容易发现,转移到下一个状态,只有两个状态:
- 发完上一条马上关机,下一次再开机;
- 发完上一条不关机。
即得方程: \[ dp[i] = dp[i - 1] + min(b, (t[i] - t[i - 1]) * a); \]
注意在0时手机就已经开机,初始代价为a而不是0。
1 | // Problem: C. Sending Messages |
D - Very Different Array
本题没有严格证明(全靠乱搞
凭直觉可以发现,最优解的序列应当是令\(a\)升序,选中的\(b\)降序,二者构成\(X\)型或八字型的趋势。
又可以发现,对于这种趋势的数列对来说,中间的部分贡献较少,两边的贡献较大,因此可以得出一个一点都不严谨的结论:在选择b序列中的数时,我们总是选择较大的那一批和较小的那一批,舍弃掉中间的部分。
根据这个结论,可以搞出一个乱搞方法:
- 将a按从小到大排序,b按从大到小排序;
- 将b前n个数与a对应位置的差处理出前缀和
s1
; - 将b后n个数与a末尾对应位置的差处理出前缀和
s2
; - 然后直接计算
s1[i]+s2[n-i+1]
的最大值。
1 | // Problem: D. Very Different Array |
E - Eat the Chip
可以发现,无论如何,每进行一步,两人的x坐标相对距离就-1。所以,只要判断x相对距离的奇偶性就能确定谁必定赢不了。
然后是确定不输的那方能否必胜。
先不讨论边界,若确定自己赢不了,这一方要做的显然是“逃离”另一方,不让它碰到自己。
而后手不输的情况下,两人行走步数相同,所以只有两人y坐标相等时才能必胜。
先手不输的情况下,先手比后手多走一步,所以两人y坐标相差1以内时先手必胜。
接下来讨论边界。容易发现,边界只会影响“逃跑者”的路径选择,所以加上一点小判断就可以了。
1 | // Problem: E. Eat the Chip |
F - Sum of Progression
看数据范围\(n \leq 1e5\),可以发现是经典的分块范围(大雾
将每个询问分为两种:
一种是步长d大于\(\sqrt n\)的,显然最多跳不超过\(\sqrt n\)次,直接暴力计算即可。
另一种是小于\(\sqrt
n\)的,我们暴力预处理出来几个数组sum[i][step],f[i][step],stp[i][step]
。
sum[i][step]
:以i为结尾、最开头是st、step为步长的数列的前缀和,即a[st] + a[st + d] + ... + a[i]
。
f[i][step]
:以i为结尾、最开头是st、step为步长的数列,每个数乘上对应系数的和,即1 * a[st] + 2 * a[st + d] + ... + k * a[i]
。
stp[i][step]
:以i为结尾、最开头是st、step为步长的数列,a[i]
对应的系数。
这些数组可以很容易的在\(\Theta(n\sqrt n)\)的时间内预处理完成。
然后,用这些数组,就可以在询问时用\(\Theta(1)\)的时间回答出问题。具体方式可以看代码。
1 | // Problem: F. Sum of Progression |
G - Mischievous Shooter
可以发现,本题相当于求一个特定图形内的1的个数的最大值,因此考虑前缀和维护。
四种不同的图形可以通过旋转矩阵合并为一种讨论,在这里以原点在左上角讨论。
我们维护4个前缀和:
sum_col[i][j]
:列前缀和,a[1][j] + a[2][j] + ... + a[i][j]
。sum_row[i][j]
:行前缀和sum_diag[i][j]
:副对角前缀和,即a[i][j] + a[i-1][j+1] + a[i-2][j+2]...
sum_f[i][j]
:以左上角为原点的霰弹图形内的个数。
通过纸上模拟可以很容易得出从[i-1][j]
和从[i][j-1]
的两种递推公式。然后可以暴力求解sum_f[1][1]
,详细的可以看代码。
处理时,要注意这题极其恶心的边界条件判断。
1 | // Problem: G. Mischievous Shooter |