ABC127
A.Ferris Wheel
Time:\(1:53\)
Dif:\(\color{Gray}{15}\)
Description:
\(\text{age}>12\to\) 全票。
\(6\leq\text{age}\leq12\to\) 半票。
\(\text{age}<6\to\) 免票。
给 \(\text{age}\) 求票价。
Code
B.Algae
Time:\(4:29\)
Dif:\(\color{Gray}{26}\)
Description:
已知 \(x_{i+1}=r\times x_i-D\) ,给 \(x_{2000},r,D\) ,求 \(x_{2001\ldots2010}\)。
Solution:
模拟即可。
Code
C.Prison
Time:\(7:42\)
Dif:\(\color{Gray}{239}\)
Description:
有 \(m\) 道关卡,第 \(i\) 道关卡想要通过,则持有的钥匙编号必须介于 \(l_i\) 与 \(r_i\) 之间。问哪些钥匙可以一发通关。
Solution1:
差分。每次 \(sum_l+1,sum_{r+1}-1\) ,最后还原出的数组有几个数 \(=m\) 就是答案。
Code
Solution2:
取 \(l_i\) 的最大值和 \(r_i\) 的最小值。介于两者之间的所有数字均成立。
D.Integer Cards
Time:\(15:11\)
Dif:\(\color{Green}{887}\)
Description
给你一个数组,每次操作可以选至多 \(b_i\) 个数修改为 \(c_i\),求所有操作结束后的最大总和。
Solution
既然我可以修改任何数,那我相当于把 \(b_i\) 个 \(c_i\) 放进数组里,最后取最大的 \(n\) 个数就是答案。
但因为 \(b_i\) 很大,因此可以开结构体存储这个数出现了几次,排序以后扫一遍即可。
Code
E.Cell Distance
Time:\(73:23\)
Dif:\(\color{Blue}{1938}\)
Description
在 \(n\times m\) 的平面内任选 \(k\) 个点 \((x_i,y_i)\),定义这种选法的权值为 \(\sum_{i=1}^{k-1}\sum_{j=i+1}^k \left| (x_i-x_j)+(y_i-y_j)\right|\)。求所有选法的权值之和模 \(10^9+7\)。\(n\times m\leq2\times10^5\)。
Solution
确定当前的这个点,设他为 \((x,y)\),则我们在这个点之前的点任选一个 \((x^\prime,y^\prime)\) ,所有的点对 \((x,y),(x^\prime,y^\prime)\) 对权值的贡献总和是可以通过等差数列求和方法计算得出的。为了选择的点数为 \(k\),我们要在剩下的 \(n\times m-2\) 个点中选择 \(k-2\) 个点。计算组合数即可。不难证明,每一个点对都被做到了。
Code
F.Absolute Minima
Time:\(0\)
Dif:\(\color{Goldenrod}{2003}\)
Description
有一个函数 \(f(x)\) ,两种操作。
- 将 \(f(x)\) 变为 \(f(x)+\left|x-a\right|+b\)。
- 求 \(f(x)\) 的最小值点。如有多个,取横坐标最小的一个。
Solution
通过初中数学知识可以发现,当 \(x\) 取到所有 \(a\) 的中位数时 \(f(x)\) 有最小值。假设已经进行了 \(2n-1\) 次操作 \(1\),每个 \(a\) 从小到大分别为 \(a_1,a_2,\ldots,a_{2n-1}\) ,则 \(x=a_n\) 时 \(f(x)=(a_n-a_1)+(a_n-a_2)+\ldots +(a_n-a_{n-1})+(a_{n+1}-a_n)+\ldots+(a_{2n-1}-a_n)+\sum b=\sum_{i=n+1}^{2n+1}a_i-\sum_{i=1}^{n-1}a_i+\sum b\)。操作次数为偶数时类似。所以我们要维护以下三个东西:
- 中位数;
- 比中位数大的数字总和;
- 比中位数小的数字总和。
于是考虑用两个堆来维护。开一个大根堆存小于中位数的数,开一个小根堆存大于中位数的数。则为了使中位数有多个时取最小的,应该让大根堆堆顶存储当前的中位数。这样大根堆中的元素个数一定大于等于小根堆中的元素个数。
考虑如何插入。如果当前的数据个数是偶数,那我们要在大根堆中新插入一个数。明显的,我要插入的数一定是小根堆堆顶和当前插入的数的最小值,并将剩下那个数放入小根堆中,这样才能保证满足原有性质。如果数据个数是偶数,类似的,取大根堆堆顶和当前数的较大值放入小根堆,剩下那个放入大根堆。这样我们就可以 \(O(n\log n)\) 维护中位数了。计算两个总和就很简单了,在数据出入堆时顺便对总和进行修改即可。