結果
| 問題 |
No.1170 Never Want to Walk
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2023-03-29 23:54:29 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 526 ms / 2,000 ms |
| コード長 | 2,844 bytes |
| コンパイル時間 | 264 ms |
| コンパイル使用メモリ | 82,164 KB |
| 実行使用メモリ | 118,916 KB |
| 最終ジャッジ日時 | 2024-09-21 14:36:16 |
| 合計ジャッジ時間 | 9,596 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 37 |
ソースコード
from typing import Callable, DefaultDict, Optional, List
from bisect import bisect_left, bisect_right
from collections import defaultdict
class UnionFindRange:
__slots__ = "part", "_n", "_parent", "_rank"
def __init__(self, n: int):
self.part = n
self._n = n
self._parent = list(range(n))
self._rank = [1] * n
def find(self, x: int) -> int:
while x != self._parent[x]:
self._parent[x] = self._parent[self._parent[x]]
x = self._parent[x]
return x
def union(self, x: int, y: int, f: Optional[Callable[[int, int], None]] = None) -> bool:
"""union后, 大的编号所在的组的指向小的编号所在的组."""
if x < y:
x, y = y, x
rootX = self.find(x)
rootY = self.find(y)
if rootX == rootY:
return False
self._parent[rootX] = rootY
self._rank[rootY] += self._rank[rootX]
self.part -= 1
if f is not None:
f(rootY, rootX)
return True
def unionRange(
self, left: int, right: int, f: Optional[Callable[[int, int], None]] = None
) -> int:
"""合并[left,right]区间, 返回合并次数."""
if left > right:
left, right = right, left
leftRoot = self.find(left)
rightRoot = self.find(right)
unionCount = 0
while rightRoot != leftRoot:
unionCount += 1
self.union(rightRoot, rightRoot - 1, f)
rightRoot = self.find(rightRoot - 1)
return unionCount
def isConnected(self, x: int, y: int) -> bool:
return self.find(x) == self.find(y)
def getSize(self, x: int) -> int:
return self._rank[self.find(x)]
def getGroup(self) -> DefaultDict[int, List[int]]:
group = defaultdict(list)
for i in range(self._n):
group[self.find(i)].append(i)
return group
if __name__ == "__main__":
# No.1170 Never Want to Walk
# https://yukicoder.me/problems/no/1170
# 数轴上有n个车站,第i个位置在xi
# 如果两个车站之间的距离di与dj满足 A<=|di-dj|<=B,则这两个车站可以相互到达,否则不能相互到达
# 对每个车站,求出从该车站出发,可以到达的车站的数量
# 1<=n<=2e5 0<=A<=B<=1e9 0<=x1<=x2<...<=xn<=1e9
# !每个车站向右合并可以到达的车站,把合并分解为单点合并+区间合并
n, A, B = map(int, input().split())
pos = list(map(int, input().split()))
uf = UnionFindRange(n)
for i, p in enumerate(pos):
left = bisect_left(pos, p + A)
right = bisect_right(pos, p + B) - 1
if right >= left: # 有可以到达的车站
uf.union(i, left)
uf.unionRange(left, right)
for i in range(n):
print(uf.getSize(i))