-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTreap.py
More file actions
167 lines (134 loc) · 3.62 KB
/
Treap.py
File metadata and controls
167 lines (134 loc) · 3.62 KB
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
from random import random
class Treap:
def __init__(self, key, value = 0):
self.key = key
self.value = value
self.priority = random()
self.size = 1
self.height = 1
self.lazy = 0
self.max_value = value
self.min_value = value
self.left = None
self.right = None
@staticmethod
def SumAll(node, value):
if node is None:
return
node.value += value
node.max_value += value
node.min_value += value
node.lazy += value
@classmethod
def Unlazy(cls, node):
cls.SumAll(node.left, node.lazy)
cls.SumAll(node.right, node.lazy)
node.lazy = 0
@classmethod
def Update(cls, node):
if node is None:
return
cls.Unlazy(node)
node.size = 1
node.height = 0
node.max_value = node.value
node.min_value = node.value
if node.left is not None:
node.size += node.left.size
node.height = node.left.height
node.max_value = max(node.max_value, node.left.max_value)
node.min_value = min(node.min_value, node.left.min_value)
if node.right is not None:
node.size += node.right.size
node.height = max(node.height, node.right.height)
node.max_value = max(node.max_value, node.right.max_value)
node.min_value = min(node.min_value, node.right.min_value)
node.height += 1
@classmethod
def SplitKeepRight(cls, node:float, key:float):
if node is None:
return None, None
left, right = None, None
cls.Unlazy(node)
if key <= node.key:
left, node.left = cls.SplitKeepRight(node.left, key)
right = node
else:
node.right, right = cls.SplitKeepRight(node.right, key)
left = node
cls.Update(left)
cls.Update(right)
return left, right
@classmethod
def Merge(cls, left, right):
if left is None:
return right
if right is None:
return left
node = None
if left.priority > right.priority:
cls.Unlazy(left)
left.right = cls.Merge(left.right, right)
node = left
else:
cls.Unlazy(right)
right.left = cls.Merge(left, right.left)
node = right
cls.Update(node)
return node
@classmethod
def SplitSmallest(cls, node):
if node is None:
return None, None
left, right = None, None
cls.Unlazy(node)
if node.left is not None:
left, node.left = cls.SplitSmallest(node.left)
right = node
else:
right = node.right
node.right = None
left = node
cls.Update(left)
cls.Update(right)
return left, right
@classmethod
def SplitGreatest(cls, node):
if node is None:
return None, None
cls.Unlazy(node)
if node.right is not None:
node.right, right = cls.SplitGreatest(node.right)
left = node
else:
left = node.left
node.left = None
right = node
cls.Update(left)
cls.Update(right)
return left, right
@staticmethod
def Size(node):
return 0 if node is None else node.size
@staticmethod
def Height(node):
return 0 if node is None else node.height
@classmethod
def _ToList(cls, node, extractor, _list = None):
if _list is None:
_list = []
if node is None:
return _list
cls.Unlazy(node)
cls._ToList(node.left, extractor, _list)
_list.append(extractor(node))
cls._ToList(node.right, extractor, _list)
return _list
@classmethod
def KeysToList(cls, node, _list = None):
extractor = lambda x: x.key
return cls._ToList(node, extractor, _list)
@classmethod
def ValuesToList(cls, node, _list = None):
extractor = lambda x: x.value
return cls._ToList(node, extractor, _list)