CF1167G tutorial

Tutorial for CF1167G

English Version

Hints

What stops the rotation?

A brute-force solution is straightforward, but how can we optimize it?

Step 1

There are two cases in which the rotation stops:

  1. the ray touches the building
  2. the building touches another building.

In the second case, write the left building is \(x\) sway from the bending point and the right one is \(y\) away from the bending point.

With some geometry knowledge, the angle is

\( \alpha=\begin{cases} \tan^{-1}(\frac{1}{x}) & x=y\\ \tan^{-1}(\frac{1}{\max(x,y)}) & |x-y|=1\\ \textrm{useless} & \textrm{otherwise} \end{cases} \)

In the third case , they won't reach each other.

So we can easily write a brute force \(O(nm)\).

code

Step 2

The crucial idea is that if \(|x|>7000\), we don't need to calculate it.

It's because, due to the "not sparse" condition that two buildings have already touched each other , or a building has already touched the ray.

Now it comes down to \(O(md)\).

Step 3

If we can represent the state before and after rotation using arrays, we only need to find positions where both values are equal to \(1\).It's easy to speed up it with bitset.

Note: some buildings may be included in the bitset but are not actually activated. A set is used to check whether a building is valid.

\(O(\frac{md}{w})\)

code

Step 4

Handwrite bitset !

code

Reference

https://codeforces.com/blog/entry/67058

https://www.cnblogs.com/yijan/p/bitset.html

中文版

Hint

是什么阻止了旋转?

暴力解法是显然的,但该如何优化?

Step 1

旋转停止有两种情况:

  1. 射线碰到某一栋建筑;
  2. 一栋建筑碰到了另一栋建筑。

在第二种情况下,设左边的建筑距离转折点为 \(x\),右边的建筑距离转折点为 \(y\)

利用一些几何知识,可以得到停止时的角度:

\( \alpha= \begin{cases} \tan^{-1}\left(\frac{1}{x}\right) & x = y \\ \tan^{-1}\left(\frac{1}{\max(x,y)}\right) & |x - y| = 1 \\ \text{无意义} & \text{其他情况} \end{cases} \)

在第三种情况下,两栋建筑不会相互接触。

因此,我们可以很容易地写出一个时间复杂度为 \(O(nm)\) 的暴力算法。

代码

Step 2

关键的观察是:当 \(|x| > 7000\) 时,我们不需要再进行计算。

这是因为在“不稀疏”的条件下,更近的两栋建筑已经发生接触,或者某一栋建筑已经先接触到了射线。

因此,时间复杂度可以降低到 \(O(md)\)

Step 3

如果我们能用数组表示旋转前后的状态,那么只需要找到前后状态都为 (1) 的位置即可。

使用 bitset 可以很容易地对这一过程进行加速。

注意:有些建筑可能被计入 bitset 中,但实际上并未被激活,因此需要使用一个集合来判断其有效性。

时间复杂度为:

\( O\left(\frac{md}{w}\right) \)

代码

Step 4

手写 bitset

代码

参考资料

https://codeforces.com/blog/entry/67058

https://www.cnblogs.com/yijan/p/bitset.html

posted @ 2026-01-02 17:23  妖灵梦  阅读(2)  评论(0)    收藏  举报