Skip to content

Commit d88619c

Browse files
authored
Create 3117-minimum-sum-of-values-by-dividing-array.js
1 parent b8a2291 commit d88619c

File tree

1 file changed

+243
-0
lines changed

1 file changed

+243
-0
lines changed
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
//#region Circular Queue
2+
/**
3+
* @template TItem
4+
*/
5+
class CircularQueue {
6+
/**
7+
* @param {number} capacity
8+
*/
9+
constructor(capacity) {
10+
/**
11+
* @private
12+
* @type {number}
13+
*/
14+
this._capacity = capacity
15+
/**
16+
* @private
17+
* @type {number}
18+
*/
19+
this._size = 0
20+
/**
21+
* @private
22+
* @type {number}
23+
*/
24+
this._bottom = 0
25+
26+
/**
27+
* @private
28+
* @type {number}
29+
*/
30+
this._maxSize = 0
31+
32+
/**
33+
* @private
34+
* @type {TItem[]}
35+
*/
36+
this._data = Array(capacity).fill(undefined)
37+
}
38+
39+
/**
40+
* @private
41+
* @param {number} index
42+
* @returns {number}
43+
*/
44+
_getCircularIndex(index) {
45+
const result = index % this._capacity
46+
if (result < 0) result += this._capacity
47+
return result
48+
}
49+
50+
get capacity() {
51+
return this._capacity
52+
}
53+
54+
get size() {
55+
return this._size
56+
}
57+
58+
get nextItem() {
59+
return this._size ? this._data[this._bottom] : undefined
60+
}
61+
62+
get lastItem() {
63+
return this._size
64+
? this._data[this._getCircularIndex(this._bottom + this._size - 1)]
65+
: undefined
66+
}
67+
68+
fromFirst(index) {
69+
return index < this._size
70+
? this._data[this._getCircularIndex(this._bottom + index)]
71+
: undefined
72+
}
73+
74+
fromLast(index) {
75+
return index < this._size
76+
? this._data[
77+
this._getCircularIndex(this._bottom + this._size - 1 - index)
78+
]
79+
: undefined
80+
}
81+
82+
/**
83+
* @param {...TItem} items
84+
*/
85+
enqueue(...items) {
86+
if (this._size + items.length > this._capacity)
87+
throw new Error('Queue capacity exceeded.')
88+
89+
let queueIndex = (this._bottom + this._size) % this._capacity
90+
this._size += items.length
91+
this._maxSize = Math.max(this._size, this._maxSize)
92+
for (let i = 0; i < items.length; ++i) {
93+
this._data[queueIndex] = items[i]
94+
queueIndex = (queueIndex + 1) % this._capacity
95+
}
96+
}
97+
98+
/**
99+
* @returns {TItem | undefined}
100+
*/
101+
dequeue() {
102+
if (!this._size) return undefined
103+
104+
const result = this._data[this._bottom]
105+
this._bottom = (this._bottom + 1) % this._capacity
106+
--this._size
107+
108+
return result
109+
}
110+
111+
/**
112+
* @returns {TItem | undefined}
113+
*/
114+
popLast() {
115+
if (!this._size) return undefined
116+
117+
--this._size
118+
const result = this._data[(this._bottom + this._size) % this._capacity]
119+
120+
return result
121+
}
122+
123+
clear() {
124+
this._size = 0
125+
}
126+
127+
get maxSize() {
128+
return this._maxSize
129+
}
130+
131+
asArray() {
132+
let res = []
133+
for (let i = 0; i < this._size; ++i) {
134+
res.push(this.fromFirst(i))
135+
}
136+
137+
return res
138+
}
139+
}
140+
//#endregion
141+
142+
let oo = 1048575
143+
let dp = new Uint32Array(10001)
144+
let dq = new CircularQueue(10001)
145+
146+
//#region Segment tree
147+
let st = new Uint32Array(40004)
148+
149+
function buildST(nums, root, l, r) {
150+
if (l == r) {
151+
st[root] = nums[l]
152+
return
153+
}
154+
155+
let m = (l + r) >> 1
156+
let c = root * 2 + 1
157+
buildST(nums, c, l, m)
158+
buildST(nums, c + 1, m + 1, r)
159+
160+
st[root] = st[c] & st[c + 1]
161+
}
162+
163+
function queryST(ql, qr, root, l, r) {
164+
if (qr < l || ql > r) return oo
165+
if (ql <= l && r <= qr) return st[root]
166+
167+
let m = (l + r) >> 1
168+
let c = root * 2 + 1
169+
let x = queryST(ql, qr, c, l, m)
170+
let y = queryST(ql, qr, c + 1, m + 1, r)
171+
172+
return x & y
173+
}
174+
//#endregion
175+
176+
177+
/**
178+
* @param {number[]} nums
179+
* @param {number[]} andValues
180+
* @return {number}
181+
*/
182+
var minimumValueSum = function (nums, andValues) {
183+
let n = nums.length
184+
let m = andValues.length
185+
buildST(nums, 0, 0, n - 1)
186+
187+
dp.fill(oo, 0, n)
188+
let a = nums[0]
189+
let t = andValues[0]
190+
for (let i = 0; i < n; ++i) {
191+
a &= nums[i]
192+
193+
if (a == t) {
194+
dp[i] = nums[i]
195+
}
196+
}
197+
198+
for (let j = 1; j < m; ++j) {
199+
dq.clear()
200+
t = andValues[j]
201+
let ll = n
202+
let rr = n - 1
203+
204+
for (let i = n - 1; i >= 0; --i) {
205+
if (rr > i) {
206+
rr = i
207+
}
208+
209+
a = queryST(rr, i, 0, 0, n - 1)
210+
while (rr > 1 && a > t && (a & nums[rr - 1]) >= t) {
211+
a &= nums[--rr]
212+
}
213+
214+
if (a != t || !rr) {
215+
dp[i] = oo
216+
continue
217+
}
218+
219+
if (ll > rr) {
220+
ll = rr
221+
dq.clear()
222+
dq.enqueue(ll - 1)
223+
}
224+
225+
while (ll > 1 && (a & nums[ll - 1]) == a) {
226+
--ll
227+
228+
while (dq.size && dp[ll - 1] <= dp[dq.fromLast(0)]) {
229+
dq.popLast()
230+
}
231+
dq.enqueue(ll - 1)
232+
}
233+
234+
while (dq.size && dq.fromFirst(0) >= rr) {
235+
dq.dequeue()
236+
}
237+
238+
dp[i] = Math.min(dp[dq.fromFirst(0)] + nums[i], oo)
239+
}
240+
}
241+
242+
return dp[n - 1] >= oo ? -1 : dp[n - 1]
243+
}

0 commit comments

Comments
 (0)