2569. 更新数组后处理求和查询 - Kotlin 线段树

Smile_slime_47

Problem: 2569. 更新数组后处理求和查询

思路

基于线段树,待补充

复杂度

时间复杂度:

空间复杂度:

Code

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
class Solution {
fun handleQuery(nums1: IntArray, nums2: IntArray, queries: Array<IntArray>): LongArray {
val tree1=SegmentTree(nums1.size)
val tree2=SegmentTree(nums2.size)
val list=ArrayList<Long>()

tree1.build(nums1)
tree2.build(nums2)

for(query in queries){
when(query[0]) {
1 -> {
tree1.reverse(query[1],query[2])
}

2 -> {
tree2.plus(0,nums2.size-1,tree1,query[1])
}

3 -> {
list.add(tree2.select(0, nums2.size - 1))
}
}
}
return list.toLongArray()
}
}

class SegmentTree(val n: Int) {
private val tree: LongArray = LongArray(4 * n) { -1 }
private val reverseMark = BooleanArray(4 * n) { false }
private val plusMark = IntArray(4 * n) { 0 }

fun build(arr: IntArray) {
build(arr, 0, n - 1, 1)
}

private fun build(arr: IntArray, left: Int, right: Int, i: Int) {
if (left == right) {
tree[i] = arr[left].toLong()
return
}

val mid = (right - left) / 2 + left

build(arr, left, mid, 2 * i)
build(arr, mid + 1, right, 2 * i + 1)

tree[i] = tree[2 * i] + tree[2 * i + 1]
}

fun select(targetLeft: Int, targetRight: Int): Long {
return select(targetLeft, targetRight, 0, n - 1, 1)
}

private fun select(targetLeft: Int, targetRight: Int, left: Int, right: Int, i: Int): Long {
if (left >= targetLeft && right <= targetRight) {
return tree[i]
}
if (right < targetLeft || left > targetRight) {
return 0
}

val mid = (right - left) / 2 + left
return select(targetLeft, targetRight, left, mid, 2 * i) + select(
targetLeft,
targetRight,
mid + 1,
right,
2 * i + 1
)
}

fun plus(targetLeft: Int, targetRight: Int, tree1: SegmentTree, p: Int) {
plus(targetLeft, targetRight, 0, n - 1, 1, tree1, p)
}

fun plus(
targetLeft: Int,
targetRight: Int,
left: Int,
right: Int,
i: Int,
tree1: SegmentTree,
p: Int
) {
if (left >= targetLeft && right <= targetRight) {
tree[i] = tree[i] + tree1.select(left, right) * p
plusMark[i] += p
return
}

val mid = (right - left) / 2 + left

if (plusMark[i] > 0 && left != right) {
tree[2 * i] = tree[2 * i] + tree1.select(left, mid) * plusMark[i]
tree[2 * i + 1] = tree[2 * i + 1] + tree1.select(mid + 1, right) * plusMark[i]

plusMark[2 * i] += plusMark[i]
plusMark[2 * i + 1] += plusMark[i]

plusMark[i] = 0
}

if (targetLeft <= mid) {
plus(targetLeft, targetRight, left, mid, 2 * i, tree1, p)
}
if (targetRight > mid) {
plus(targetLeft, targetRight, mid + 1, right, 2 * i + 1, tree1, p)
}

tree[i] = tree[2 * i] + tree[2 * i + 1]
}

fun reverse(targetLeft: Int, targetRight: Int) {
reverse(targetLeft, targetRight, 0, n - 1, 1)
}

fun reverse(
targetLeft: Int,
targetRight: Int,
left: Int,
right: Int,
i: Int
) {
if (left >= targetLeft && right <= targetRight) {
tree[i] = right - left + 1 - tree[i]
reverseMark[i] = !reverseMark[i]
return
}

val mid = (right - left) / 2 + left

if (reverseMark[i] && left != right) {
tree[2 * i] = (mid - left + 1) - tree[2 * i]
tree[2 * i + 1] = (right - (mid + 1) + 1) - tree[2 * i + 1]

reverseMark[2 * i] = !reverseMark[2 * i]
reverseMark[2 * i + 1] = !reverseMark[2 * i + 1]

reverseMark[i] = false
}

if (targetLeft <= mid) {
reverse(targetLeft, targetRight, left, mid, 2 * i)
}
if (targetRight > mid) {
reverse(targetLeft, targetRight, mid + 1, right, 2 * i + 1)
}

tree[i] = tree[2 * i] + tree[2 * i + 1]
}
}
Comments
On this page
2569. 更新数组后处理求和查询 - Kotlin 线段树