提供一个 L 题的 python 题解。本题是约瑟夫环问题的优化模拟,核心在于:(1)过程中高效维护已经删去的位置;(2)并快速找到下一个跳到的位置。
考虑使用线段树(当然是码量更小的树状数组啦),对于(1),将对应位置置零即可;对于(2),在前缀和上二分,找到当前位置往后推的第 m 个位置即可。对于环形,取模即可,细节:为了能取到 n,稍微处理一下(见代码)。
class Fenwick:
__slots__ = 'tree'
def __init__(self, n):
self.tree = [0] * (n + 1)
def add_delta(self, i: int, delta: int) -> None:
while i < len(self.tree):
self.tree[i] += delta
i += i & -i
def pre(self, i: int) -> int:
res = 0
while i > 0:
res += self.tree[i]
i &= i - 1
return res
def find_kth(self, k: int) -> int:
left, right = 1, len(self.tree)
while left < right:
mid = (left + right) // 2
if self.pre(mid) < k: left = mid + 1
else: right = mid
return left
def solve():
n, m = mii()
T = Fenwick(n)
for i in range(1, n + 1): T.add_delta(i, 1)
res = []
cur = 1
while n > 1:
cur = (cur - 1 + m - 1) % n + 1
nxt = T.find_kth(cur)
res.append(nxt)
T.add_delta(nxt, -1)
n -= 1
print(*res)