AtCoder Beginner Contest 183
A - ReLU
输入,输出。
B - Billiards
假设向点\((x, 0)\)处踢符合条件,此时根据反射角相等可以得到\(\frac{S_y}{x - S_x} = \frac{G_y}{G_x - x}\),解得\(x = \frac{S_x \cdot G_y + S_y \cdot G_x}{G_y + S_y}\)。
C - Travel
利用std里的next_permutation
函数枚举所有排列,然后模拟就完事了。
D - Water Heater
把人看成两个操作,在\(S_i\)时执行\(sum = sum + p_i\),在\(T_i\)时执行\(sum = sum - p_i\)。
注意到时间的值域为\([0, 2 \times 10^5]\),所以可以扫一遍时间,把当前时刻发生的操作执行完之后判断一下就完事了。注意要先删再加。
如果存在某个时间\(sum\)大于\(W\),则输出NO,否则输出YES。
E - Queen on Grid
很明显的一道DP题。
记\(dp_{i, j}\)为从\((1, 1)\)走到\((i, j)\)的方法数。则\(dp_{i, j}\)可以从三个方向转移过来:左,上,左上。如果枚举每个方向,然后暴力扫一遍这个方向上直至遇到墙的所有点,用这些点来更新当前点,那么就可以得到一个\(O(n^3)\)的DP。
很明显,这个复杂度在这题的数据量下会TLE,所以需要再优化一下。
利用前缀和的思想去优化就可以将这题优化到\(O(n^2)\)。
F - Confluence
题面明示了这题并查集。
为每个节点开一个map,map[id]表示以这个点为代表节点的集合中,\(id\)班的学生数量。
在并查集merge
操作的时候,可能会合并两个集和,这个时候只需要合并两个代表节点的map,就可以得到合并之后的结果。
但是有一个问题就是暴力合并的话时间复杂度会被卡到\(O(n^2)\)。比如构造数据,从左至右不断合并,这个时候的时间复杂度就是\(\sum_{i = 1}^{n - 1}i = O(n^2)\)。
利用启发式合并去优化,既每次merge
的时候,总是将较小的那个集和合并到另外一个集和,这样时间复杂度可以优化到\(O(n \log n)\)。