Hard
You are given an integer array nums of length n and an integer p.
A non-empty subsequence of nums is called good if:
n.p.You are also given a 2D integer array queries of length q, where each queries[i] = [indi, vali] indicates that you should update nums[indi] to vali.
After each query, determine whether there exists any good subsequence in the current array.
Return the number of queries for which a good subsequence exists.
The term gcd(a, b) denotes the greatest common divisor of a and b.
Example 1:
Input: nums = [4,8,12,16], p = 2, queries = [[0,3],[2,6]]
Output: 1
Explanation:
| i | [ind_i, val_i] |
Operation | Updated nums |
Any good Subsequence |
|---|---|---|---|---|
| 0 | [0, 3] |
Update nums[0] to 3 |
[3, 8, 12, 16] |
No, as no subsequence has GCD exactly p = 2 |
| 1 | [2, 6] |
Update nums[2] to 6 |
[3, 8, 6, 16] |
Yes, subsequence [8, 6] has GCD exactly p = 2 |
Thus, the answer is 1.
Example 2:
Input: nums = [4,5,7,8], p = 3, queries = [[0,6],[1,9],[2,3]]
Output: 2
Explanation:
| i | [ind_i, val_i] |
Operation | Updated nums |
Any good Subsequence |
|---|---|---|---|---|
| 0 | [0, 6] |
Update nums[0] to 6 |
[6, 5, 7, 8] |
No, as no subsequence has GCD exactly p = 3 |
| 1 | [1, 9] |
Update nums[1] to 9 |
[6, 9, 7, 8] |
Yes, subsequence [6, 9] has GCD exactly p = 3 |
| 2 | [2, 3] |
Update nums[2] to 3 |
[6, 9, 3, 8] |
Yes, subsequence [6, 9, 3] has GCD exactly p = 3 |
Thus, the answer is 2.
Example 3:
Input: nums = [5,7,9], p = 2, queries = [[1,4],[2,8]]
Output: 0
Explanation:
| i | [ind_i, val_i] |
Operation | Updated nums |
Any good Subsequence |
|---|---|---|---|---|
| 0 | [1, 4] |
Update nums[1] to 4 |
[5, 4, 9] |
No, as no subsequence has GCD exactly p = 2 |
| 1 | [2, 8] |
Update nums[2] to 8 |
[5, 4, 8] |
No, as no subsequence has GCD exactly p = 2 |
Thus, the answer is 0.
Constraints:
2 <= n == nums.length <= 5 * 1041 <= nums[i] <= 5 * 1041 <= queries.length <= 5 * 104queries[i] = [indi, vali]1 <= vali, p <= 5 * 1040 <= indi <= n - 1class Solution {
private lateinit var tree: IntArray
private var validCount = 0
fun countGoodSubseq(nums: IntArray, p: Int, queries: Array<IntArray>): Int {
val n = nums.size
// 1. Iterative Segment Tree only needs 2n space
tree = IntArray(2 * n)
// Build the leaves of the tree and get initial count
for (i in 0..<n) {
if (nums[i] % p == 0) {
tree[n + i] = nums[i]
validCount++
}
}
// Build the internal nodes bottom-up
for (i in n - 1 downTo 1) {
// tree[i << 1] is the left child, tree[i << 1 | 1] is the right child
tree[i] = gcd(tree[i shl 1], tree[i shl 1 or 1])
}
var ans = 0
for (q in queries) {
val idx = q[0]
val value = q[1]
// 2. O(1) tracking for validCount (No segment tree needed for this!)
val wasValid = (nums[idx] % p == 0)
val isValid = (value % p == 0)
if (wasValid && !isValid) {
validCount--
}
if (!wasValid && isValid) {
validCount++
}
// Update the original array to keep track of the old values
nums[idx] = value
// Point update for the Iterative Tree
tree[idx + n] = if (isValid) value else 0
// Climb up the tree using bitwise shifts (i >>= 1 means i = i / 2)
var i = idx + n
while (i > 1) {
tree[i shr 1] = gcd(tree[i], tree[i xor 1])
i = i shr 1
}
// 3. The logic check (tree[1] is ALWAYS the root in an iterative tree)
if (tree[1] == p) {
if (validCount < n) {
ans++
} else {
// validCount == n (Every element is a multiple of p)
if (n > 20) {
// THE O(1) MATH BYPASS!
ans++
} else {
// Only run this heavy check if n is 20 or smaller
var flag = false
for (i in 0..<n) {
val leftGcd = query(0, i - 1, n)
val rightGcd = query(i + 1, n - 1, n)
if (gcd(leftGcd, rightGcd) == p) {
flag = true
break
}
}
if (flag) {
ans++
}
}
}
}
}
return ans
}
// Iterative Range Query [l, r] inclusive
private fun query(l: Int, r: Int, n: Int): Int {
var l = l
var r = r
if (l > r) {
return 0
}
var res = 0
l += n
r += n + 1
while (l < r) {
if ((l and 1) == 1) {
res = gcd(res, tree[l++])
}
if ((r and 1) == 1) {
res = gcd(res, tree[--r])
}
l = l shr 1
r = r shr 1
}
return res
}
private fun gcd(a: Int, b: Int): Int {
var a = a
var b = b
while (b > 0) {
val temp = b
b = a % b
a = temp
}
return a
}
}