QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#526515 | #5898. Havannah | 320x200 | 20 ✓ | 2084ms | 575304kb | Python3 | 4.3kb | 2024-08-21 16:59:29 | 2024-08-21 16:59:34 |
Judging History
answer
from sys import stdin, stderr
DELTAS = [(+1, +1), (0, +1), (-1, 0), (-1, -1), (0, -1), (+1, 0)]
CORNER_MASK = 0b10101010101
SIDE_MASK = CORNER_MASK << 1
class Board:
def __init__(self, S):
self.S = S
self.D = S * 2 - 1
self.rep = [[None] * self.D for _ in range(self.D)]
def which_corner_or_side(self, x, y):
corner = (0 if x == self.D and y == self.D else
2 if x == self.S and y == self.D else
4 if x == 1 and y == self.S else
6 if x == 1 and y == 1 else
8 if x == self.S and y == 1 else
10 if x == self.D and y == self.S else
None)
if corner is not None:
return 1 << corner
side = (1 if y == self.D and x >= self.S else
3 if x + self.S - 1 == y else
5 if x == 1 and y <= self.S else
7 if y == 1 and x <= self.S else
9 if y + self.S - 1 == x else
11 if x == self.D and y >= self.S else
None)
if side is not None:
return 1 << side
return 0
def dist_to_center(self, x, y):
dx, dy = x - self.S, y - self.S
return max(dx, dy, 0) - min(dx, dy, 0)
def mark(self, x, y):
assert self.rep[x - 1][y - 1] is None
self.rep[x - 1][y - 1] = (x, y, self.which_corner_or_side(x, y))
return self.rep[x - 1][y - 1]
def is_onboard(self, x, y):
return 1 <= x <= self.D and 1 <= y <= self.D and abs(x - y) < self.S
def has_parent(self, x, y):
self_rep = self.rep[x - 1][y - 1]
return self_rep is not None and self_rep[:2] != (x, y)
def find(self, x, y, corner_or_side=None):
if not self.is_onboard(x, y):
return None
if not self.has_parent(x, y):
return self.rep[x - 1][y - 1]
self.rep[x - 1][y - 1] = self.find(*self.rep[x - 1][y - 1])
return self.rep[x - 1][y - 1]
def propagate(self, x, y, rep_value):
while self.rep[x - 1][y - 1] != rep_value:
old_rep_value = self.rep[x - 1][y - 1]
self.rep[x - 1][y - 1] = rep_value
x, y, _ = old_rep_value
def union(self, x1, y1, x2, y2):
x1, y1, corner_or_side1 = self.find(x1, y1)
x2, y2, corner_or_side2 = self.find(x2, y2)
merged = ((x1, y1) if self.dist_to_center(x1, y1) >= self.dist_to_center(x2, y2) else (x2, y2)) + (
corner_or_side1 | corner_or_side2,)
self.propagate(x1, y1, merged)
self.propagate(x2, y2, merged)
if __name__ == "__main__":
T = int(stdin.readline())
for t in range(T):
S, M = map(int, stdin.readline().split())
stderr.write(f"{S} {M}\n")
board = Board(S)
result = ""
for k in range(M):
x, y = map(int, stdin.readline().split())
if result:
continue
if board.find(x, y) is not None:
continue
wins = []
neigh_reps = []
dx, dy = DELTAS[-1]
last_neigh_rep = board.find(x + dx, y + dy)
for dx, dy in DELTAS:
neigh_rep = board.find(x + dx, y + dy)
if last_neigh_rep is None and neigh_rep is not None:
neigh_reps.append(neigh_rep)
last_neigh_rep = neigh_rep
if len(neigh_reps) > 1 and any(True for i in range(len(neigh_reps)) if neigh_reps[i-1] == neigh_reps[i]):
wins.append("ring")
board.mark(x, y)
for dx, dy in DELTAS:
nx, ny = x + dx, y + dy
if board.find(nx, ny) is None:
continue
board.union(x, y, nx, ny)
*_, corner_or_side = board.find(x, y)
if (corner_or_side & CORNER_MASK).bit_count() >= 2:
wins.append("bridge")
if (corner_or_side & SIDE_MASK).bit_count() >= 3:
wins.append("fork")
if wins:
wins.sort()
result =f"{'-'.join(wins)} in move {k + 1}"
if not result:
result = "none"
print(f"Case #{t + 1}: {result}")
Details
Tip: Click on the bar to expand more detailed information
Subtask #1:
score: 8
Accepted
Test #1:
score: 8
Accepted
time: 145ms
memory: 11088kb
input:
200 49 99 13 45 37 85 4 3 9 3 47 1 39 1 97 71 31 2 37 1 48 3 4 2 47 2 16 1 6 3 70 27 38 2 13 56 39 3 23 21 45 17 38 1 10 3 13 8 13 2 19 2 7 1 2 2 21 3 13 3 15 1 40 61 6 1 45 1 45 3 15 59 5 3 26 1 78 72 51 78 46 1 35 2 29 2 37 2 43 3 8 2 12 2 16 3 29 3 46 2 16 2 30 3 5 2 12 3 15 25 10 1 19 3 49 1 66 ...
output:
Case #1: ring in move 88 Case #2: ring in move 49 Case #3: none Case #4: ring in move 74 Case #5: none Case #6: ring in move 92 Case #7: none Case #8: none Case #9: none Case #10: none Case #11: none Case #12: none Case #13: ring in move 51 Case #14: ring in move 76 Case #15: ring in move 51 Case #1...
result:
ok 200 lines
Subtask #2:
score: 12
Accepted
Test #2:
score: 12
Accepted
time: 2084ms
memory: 575304kb
input:
20 3000 1799 2800 3000 2800 2800 3000 2800 3200 3000 3200 3200 3000 3200 2800 2999 2801 2800 3001 2801 3200 3001 3199 3200 2999 3199 2800 2998 2802 2800 3002 2802 3200 3002 3198 3200 2998 3198 2800 2997 2803 2800 3003 2803 3200 3003 3197 3200 2997 3197 2800 2996 2804 2800 3004 2804 3200 3004 3196 32...
output:
Case #1: ring in move 1799 Case #2: bridge-ring in move 9 Case #3: none Case #4: ring in move 1799 Case #5: fork-ring in move 9 Case #6: bridge-fork-ring in move 15 Case #7: none Case #8: ring in move 1799 Case #9: none Case #10: bridge-fork in move 5 Case #11: bridge in move 2 Case #12: ring in mov...
result:
ok 20 lines
Extra Test:
score: 0
Extra Test Passed