QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#526371 | #5898. Havannah | 320x200 | 0 | 2184ms | 575208kb | Python3 | 4.6kb | 2024-08-21 14:30:50 | 2024-08-21 14:30:50 |
Judging History
answer
from sys import stdin
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 None
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
corner_or_side = self.which_corner_or_side(x, y)
self.rep[x - 1][y - 1] = corner_or_side if corner_or_side is not None else (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 not isinstance(self_rep, int) and self_rep != (x, y)
def find(self, x, y):
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 True:
old_rep_value = self.rep[x - 1][y - 1]
self.rep[x - 1][y - 1] = rep_value
if self.has_parent(x, y):
x, y = old_rep_value
else:
break
def union(self, x1, y1, x2, y2):
rep1 = self.find(x1, y1)
assert rep1 is not None
rep2 = self.find(x2, y2)
assert rep2 is not None
if isinstance(rep1, int):
merged = rep1 | rep2 if isinstance(rep2, int) else rep1
else:
merged = rep2 if isinstance(rep2, int) else (rep1 if self.dist_to_center(*rep1) >= self.dist_to_center(*rep2) else rep2)
if rep1 != merged:
self.propagate(x1, y1, merged)
if rep2 != 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())
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(i for i in range(len(neigh_reps)) if neigh_reps[i-1] == neigh_reps[i]):
wins.append("ring")
self_rep = 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)
self_rep = board.find(x, y)
if isinstance(self_rep, int):
if (self_rep & CORNER_MASK).bit_count() >= 2:
wins.append("bridge")
if (self_rep & 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: 0
Wrong Answer
Test #1:
score: 0
Wrong Answer
time: 108ms
memory: 11100kb
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 21 Case #2: ring in move 39 Case #3: none Case #4: ring in move 59 Case #5: none Case #6: ring in move 42 Case #7: none Case #8: ring in move 40 Case #9: none Case #10: none Case #11: none Case #12: none Case #13: ring in move 54 Case #14: ring in move 61 Case #15: ring in move...
result:
wrong answer 1st lines differ - expected: 'Case #1: ring in move 88', found: 'Case #1: ring in move 21'
Subtask #2:
score: 0
Wrong Answer
Test #2:
score: 0
Wrong Answer
time: 2184ms
memory: 575208kb
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 in move 9 Case #3: none Case #4: ring in move 1799 Case #5: fork 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 move 6 Case #...
result:
wrong answer 2nd lines differ - expected: 'Case #2: bridge-ring in move 9', found: 'Case #2: bridge in move 9'