-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSplitMergeTreap.kt
130 lines (113 loc) · 3.23 KB
/
SplitMergeTreap.kt
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
class SplitMergeTreap {
private data class Node(
val value: Int,
var l: Node? = null,
var r: Node? = null,
var count: Int = 1,
) {
val priority = Random.nextInt()
var size: Int = count
fun updateSize() {
size = count + l.size + r.size
}
}
private var root: Node? = null
fun add(value: Int) {
val (l, r) = root.split(value)
var (ll, lr) = l.split(value - 1)
if (lr == null) {
lr = Node(value)
} else {
lr.count++
lr.updateSize()
}
root = merge(merge(ll, lr), r)
}
fun del(value: Int) {
val (l, r) = root.split(value)
var (ll, lr) = l.split(value - 1)
if (lr != null && lr.count > 1) {
lr.count--
lr.updateSize()
ll = merge(ll, lr)
}
root = merge(ll, r)
}
val size: Int
get() = root.size
fun rank(value: Int): Int {
val (l, r) = root.split(value - 1)
return l.size.also { root = merge(l, r) }
}
operator fun get(rank: Int): Int {
val (v, node) = root!!.getByRank(rank)
root = node
return v
}
fun previous(value: Int): Int {
val (l, r) = root.split(value - 1)
val (p, node) = l!!.getByRank(l.size - 1)
root = merge(node, r)
return p
}
fun next(value: Int): Int {
val (l, r) = root.split(value)
val (p, node) = r!!.getByRank(0)
root = merge(l, node)
return p
}
private companion object {
val Node?.size: Int
get() = this?.size ?: 0
fun Node?.split(key: Int): Pair<Node?, Node?> = when {
this == null -> null to null
value <= key -> {
val (rl, rr) = r.split(key)
r = rl
updateSize()
this to rr
}
else -> {
val (ll, lr) = l.split(key)
l = lr
updateSize()
ll to this
}
}
fun Node?.splitByRank(rank: Int): Triple<Node?, Node?, Node?> = when {
this == null -> Triple(null, null, null)
rank < l.size -> {
val (ll, lm, lr) = l.splitByRank(rank)
l = lr
updateSize()
Triple(ll, lm, this)
}
rank < l.size + count -> Triple(l, this, r).also {
l = null
r = null
}
else -> {
val (rl, rm, rr) = r.splitByRank(rank - l.size - count)
r = rl
updateSize()
Triple(this, rm, rr)
}
}
fun merge(u: Node?, v: Node?): Node? = when {
u == null -> v
v == null -> u
u.priority < v.priority -> u.apply {
r = merge(r, v)
updateSize()
}
else -> v.apply {
l = merge(u, l)
updateSize()
}
}
fun Node.getByRank(rank: Int): Pair<Int, Node> {
val (l, m, r) = splitByRank(rank)
return m!!.value to merge(merge(l, m), r)!!
}
}
}