QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#526515#5898. Havannah320x20020 ✓2084ms575304kbPython34.3kb2024-08-21 16:59:292024-08-21 16:59:34

Judging History

你现在查看的是最新测评结果

  • [2024-08-21 16:59:34]
  • 评测
  • 测评结果:20
  • 用时:2084ms
  • 内存:575304kb
  • [2024-08-21 16:59:29]
  • 提交

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