-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclinic.py
93 lines (74 loc) · 2.5 KB
/
clinic.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
""" https://coderun.yandex.ru/problem/goblins-and-chess """
class Node:
"""Double-linked list node"""
def __init__(self, value=None):
self.value = value
self.next = None
self.prev = None
def connect(self, next=None, prev=None):
self.next = next
self.prev = prev
if next:
next.prev = self
if prev:
prev.next = self
def walk(self):
node = self
while node:
yield str(node.value)
node = node.next
class Pointer:
"""Pointer to the node together with its place in the queue"""
def __init__(self, node: Node, index: int):
self.node = node
self.index = index
def move(self, target: int):
while target > self.index:
self.node = self.node.next
self.index += 1
while target < self.index:
self.node = self.node.prev
self.index -= 1
def correct(self, delta):
self.index += delta
def __str__(self):
return f"[#{self.index}] " + "->".join(self.node.walk())
def main():
"""Solve the clinic problem with three pointers"""
N = int(input())
head = Pointer(Node(), 0)
middle = Pointer(head.node, 0)
tail = Pointer(Node(), 1)
tail.node.connect(prev=head.node)
# middle points to the center as defined by index len(tail) // 2
# 0 elements: tail=1, middle=head=0
# 1 element: tail=2, middle=1, head=0
# 2 elements: tail=3, 2, middle=1, head=0
# we always insert between tail and middle
for _ in range(N):
s = input()
# print(head, middle, s, sep=" | ")
if s[0] == "-":
del_node = head.node.next
print(del_node.value)
head.node.connect(next=del_node.next)
if middle.index == 1:
assert del_node == middle.node
middle = Pointer(head.node.next, 1)
else:
assert del_node != middle.node
middle.correct(-1)
tail.correct(-1)
else:
new_node = Node(int(s.split()[1].strip()))
if s[0] == "*":
# insert after the middle
new_node.connect(prev=middle.node, next=middle.node.next)
else:
assert s[0] == "+"
# insert before the tail
new_node.connect(prev=tail.node.prev, next=tail.node)
tail.correct(+1)
middle.move(tail.index // 2)
if __name__ == "__main__":
main()