forked from doocs/leetcode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSolution.swift
133 lines (119 loc) · 3.25 KB
/
Solution.swift
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
class Node {
var left: Node?
var right: Node?
let l: Int
let r: Int
let mid: Int
var v = 0
var add = 0
init(_ l: Int, _ r: Int) {
self.l = l
self.r = r
self.mid = (l + r) >> 1
}
}
class SegmentTree {
private var root: Node
private let MOD = 1_000_000_007
init(_ n: Int) {
root = Node(1, n)
}
func modify(_ l: Int, _ r: Int, _ v: Int) {
modify(l, r, v, root)
}
private func modify(_ l: Int, _ r: Int, _ v: Int, _ node: Node) {
if l > r {
return
}
if node.l >= l && node.r <= r {
node.v = (node.v + (node.r - node.l + 1) * v) % MOD
node.add = (node.add + v) % MOD
return
}
pushdown(node)
if l <= node.mid {
modify(l, r, v, node.left!)
}
if r > node.mid {
modify(l, r, v, node.right!)
}
pushup(node)
}
func query(_ l: Int, _ r: Int) -> Int {
return query(l, r, root)
}
private func query(_ l: Int, _ r: Int, _ node: Node) -> Int {
if l > r {
return 0
}
if node.l >= l && node.r <= r {
return node.v
}
pushdown(node)
var v = 0
if l <= node.mid {
v = (v + query(l, r, node.left!)) % MOD
}
if r > node.mid {
v = (v + query(l, r, node.right!)) % MOD
}
return v
}
private func pushup(_ node: Node) {
node.v = (node.left!.v + node.right!.v) % MOD
}
private func pushdown(_ node: Node) {
if node.left == nil {
node.left = Node(node.l, node.mid)
}
if node.right == nil {
node.right = Node(node.mid + 1, node.r)
}
if node.add != 0 {
let left = node.left!, right = node.right!
left.v = (left.v + (left.r - left.l + 1) * node.add) % MOD
right.v = (right.v + (right.r - right.l + 1) * node.add) % MOD
left.add = (left.add + node.add) % MOD
right.add = (right.add + node.add) % MOD
node.add = 0
}
}
}
class Solution {
private var g: [[Int]] = []
private var begin: [Int] = []
private var end: [Int] = []
private var idx = 1
func bonus(_ n: Int, _ leadership: [[Int]], _ operations: [[Int]]) -> [Int] {
g = Array(repeating: [], count: n + 1)
for l in leadership {
let (a, b) = (l[0], l[1])
g[a].append(b)
}
begin = Array(repeating: 0, count: n + 1)
end = Array(repeating: 0, count: n + 1)
idx = 1
dfs(1)
var ans: [Int] = []
let tree = SegmentTree(n)
for op in operations {
let (p, v) = (op[0], op[1])
if p == 1 {
tree.modify(begin[v], begin[v], op[2])
} else if p == 2 {
tree.modify(begin[v], end[v], op[2])
} else if p == 3 {
ans.append(tree.query(begin[v], end[v]))
}
}
return ans
}
private func dfs(_ u: Int) {
begin[u] = idx
for v in g[u] {
dfs(v)
}
end[u] = idx
idx += 1
}
}