AtCoder Beginner Contest 255 A—E
A
题目描述
给定一个的$ \ 2 \times 2 \ $矩阵$ \ A \ $,输出其中的值$ \ A_{R,C} \ $。
题目分析
时间复杂度:$O(1)$。
输入就行嘞。
$Code$
1 | int n, m; |
$ \ $
$ \ $
B
题目描述
有$ \ N \ $个人在位置为$(X_i,Y_i)$的位置上。
其中有$ \ K \ $个人是特殊人~~(被选中的孩子)~~,能够发射光芒。
当一个人位于$ \ (x,y) \ $坐标发射半径为$ \ R \ $的光芒时候,能够照亮以$ \ (x,y) \ $为圆心,半径为$ \ R \ $的一个光圈(包括边界)。
找到最小的半径使得所有特殊人能够将所有人都照耀。
题目分析
时间复杂度:$O(nk)$。
要使得所有人都能够被照耀到,即需要求出每个人到特殊人距离的最小值(因为只用被一个特殊人照射即可,所以取最近的特殊人的位置),然后在这些最小值中取最大值即可。
$Code$
1 |
|
$ \ $
$ \ $
C
题目描述
给定一个整数$ \ X \ $,如下的操作会被记为一次操作。
- 选择并做一下其中一项操作
- 给$ \ X \ $加$ \ 1 \ $
- 给$ \ X \ $减$ \ 1 \ $
给定一个首项为$ \ A \ $,公差为$ \ D \ $,一共$ \ N \ $项的等差数组$ \ S \ $。
问经过多少次操作才能将$ \ X \ $变为等差数组$ \ S \ $中的一个数。
题目分析
时间复杂度:$O(1)$。
分情况讨论即可。
详见代码注释。
$Code$
1 | const int N = 110; |
$ \ $
$ \ $
D
题目描述
给定一个数组$ \ N:A = (A_1,A_2,…,A_N) \ $,如下的操作会被记为一次操作。
- 首先,选择一个$ \ 1 \ $到$ \ N \ $中的一个位置$ \ A_i \ $。
- 接下来,选择其中一项进行操作
- 给$ \ A_i \ $加$ \ 1 \ $
- 给$ \ A_i \ $减$ \ 1 \ $
有$ \ Q \ $个询问。
每个询问如下:
- 找到使得数组$ \ N \ $中的每一个元素都变为$ \ X \ $的最小步骤为多少?
题目分析
时间复杂度:$O(1)$。
对于案例
1 | N:6 11 2 5 5 |
如果暴力计算每个与$ \ X \ $的差的绝对值,那么是恐怖的$O(n^2)$。
因此需要优化。
如果我们对$ \ N \ $进行排序后:
1 | N:2 5 5 6 11 |
我们能够发现对于数字$ \ 5 \ $来说,它之前的数$ \ A_i \ $一定小于$ \ 5 \ $, 它之后的数$ \ A_j \ $一定大于$ \ 5 \ $, 那么如果我们能够将某个数字$ \ A \ $比它小的所有数和比它大的所有数统计出来,就能优化计算。这就可以用到前缀和的知识了
如何优化计算?
首先不用判断正负号。
然后计算这个数前面的所有数变为X所需要的数字:$cnt(前面所有数的个数) \times X - sum(前面的所有数的和)$ 。
计算这个数后面的所有数变为X所需要的数字:$sum(后面的所有数的和) - cnt(后面所有数的个数) \times X$ 。
这里又要涉及到如何快速找到数$ \ A \ $的下标,可以使用二分
STL库函数
lower_bound/upper_bound
二分
lower_bound
的第三个参数传入一个元素x
,在两个迭代器(指针)指定的部分上执行二分查找,返回指向第一个大于等于x
的元素的位置的迭代器(指针)。
upper_bound
的用法和lower_bound
大致相同,唯一的区间就是查找的第一个大于x
的元素。当然,两个迭代器(指针)指定的部分应该是提前排好序的。
在有序int
数组(元素放在下标1 ~ n
)中查找大于等于x
的最小整数的下标:
1 | int i = lower_bound(a + 1, a + 1 + n, x) - a; |
$Code$
1 | const int N = 200010; |
$ \ $
$ \ $
E
题目描述
给定长度为$ \ N - 1 \ $的数组$S = (S_1,S_2,…,S_{N - 1})$,以及$ \ M \ $个被称为幸运数的数字。
一个长度为$ \ N \ $的数组$A = (A_1, A_2,…,A_N)$的数组,满足如下情况:
$A_i + A_{i + 1} = S_i$,对于$i \in [1,N - 1]$都成立
找到一组数组$ \ A \ $,使得其中包含的幸运数字足够多。
题目分析
时间复杂度:$O(nmlogn)$。
枚举每一位$\ A_i \ $为幸运数字的情况,那么$ \ A \ $数组的第一位就可以被计算出来(因为只要确定一个数后,所有的数都可以确定出来)。
假设当前位置为$ \ i \ $枚举的幸运数为$ \ x \ $,通过计算可以得到$ \ A_1 \ $,我们假设它为$ \ y \ $,也就是说当$ \ A_1 \ $为$ \ y \ $的时候,在当前位置$ \ i \ $会出现一个幸运数$ \ x \ $。
我们用map<long long, int> cnt
来统计$ \ cnt[x] \ $如果第一位数字为$ \ y \ $,那么它就有$ \ cnt[y] \ $个幸运数。在所有情况中取一个最大值即可。
知道了其中一个数如何求第一个数呢?
我们知道:
$$A_1 + A_2 = S_1$$
$$A_2 + A_3 = S_2$$
$$A_3 + A_4 = S_3$$
$$…$$
$$A_{N-1} + A_N = S_{N-1}$$
假设$ \ A_4 \ $为幸运数$ \ x \ $,那么通过上面的等式可以计算出$ \ A_1 \ $为$ \ S_1 - S_2 + S_3 - x \ $。
假设$ \ A_3 \ $为幸运数$ \ x \ $,那么通过上面的等式可以计算出$ \ A_1 \ $为$ \ S_1 - S_2 + x \ $。
注意当$ \ A_i \ $的位数偶数时需要$ \ -x \ $,而当$ \ A_i \ $的位数奇数时需要$ \ +x \ $。
为了更快速的统计出$ \ \sum S \ $,我们可以通过一个$ \ sum \ $数组来记录$ \ \sum_{i=1}^n (-1)^{n+1}S_i \ $
$Code$
1 |
|
$ \ $
$ \ $
题目分析
时间复杂度:$O(1)$。
$Code$
$ \ $
$ \ $
F(先空着-。-)
题目描述
题目分析
时间复杂度:$O(1)$。
$Code$
$ \ $
$ \ $