资讯中心

Kimi LeetCode 3901. 好子序列查询 Golang实现

📅 2026/8/14 16:11:33
Kimi    LeetCode 3901. 好子序列查询 Golang实现
根据搜索结果LeetCode 3901「好子序列查询」的 Go 实现如下---思路1. 只关心 p 的倍数如果 nums[i] 不是 p 的倍数它对 GCD 为 p 的子序列没有贡献在线段树中视为 0。2. 线段树维护所有 p 倍数的 GCD记为 g。- 若 g ! p则不存在好子序列。- 若 g p则所有 p 的倍数整体 GCD 已是 p。3. 长度严格小于 n- 若 cnt n并非所有元素都是 p 的倍数直接取所有 p 的倍数即可长度必然 n。- 若 cnt n所有元素都是 p 的倍数需要删一个元素后 GCD 仍为 p。- 关键结论若 n 6 且整体 GCD 为 p则一定可以删一个元素使 GCD 仍为 p。因此只需在 n 6 时暴力枚举删除位置。4. 线段树操作单点更新、区间查询 GCD。---Go 实现gofunc gcd(a, b int) int {for b ! 0 {a, b b, a%b}return a}type Node struct {l, r intg int}func NewNode(l, r int) *Node {return Node{l: l, r: r, g: 0}}type SegmentTree struct {tr []*Node}func NewSegmentTree(n int) *SegmentTree {tree : SegmentTree{tr: make([]*Node, n2)}tree.build(1, 1, n)return tree}func (st *SegmentTree) build(u, l, r int) {st.tr[u] NewNode(l, r)if l r {return}mid : (l r) 1st.build(u1, l, mid)st.build(u1|1, mid1, r)}func (st *SegmentTree) pushup(u int) {st.tr[u].g gcd(st.tr[u1].g, st.tr[u1|1].g)}func (st *SegmentTree) modify(u, x, v int) {if st.tr[u].l st.tr[u].r {st.tr[u].g vreturn}mid : (st.tr[u].l st.tr[u].r) 1if x mid {st.modify(u1, x, v)} else {st.modify(u1|1, x, v)}st.pushup(u)}func (st *SegmentTree) query(u, l, r int) int {if l r {return 0}if st.tr[u].l l st.tr[u].r r {return st.tr[u].g}mid : (st.tr[u].l st.tr[u].r) 1if r mid {return st.query(u1, l, r)}if l mid {return st.query(u1|1, l, r)}return gcd(st.query(u1, l, mid), st.query(u1|1, mid1, r))}func countGoodSubseq(nums []int, p int, queries [][]int) int {n : len(nums)tree : NewSegmentTree(n)cnt : 0for i, x : range nums {if x%p 0 {tree.modify(1, i1, x)cnt}}ans : 0for _, q : range queries {idx, val : q[0], q[1]if nums[idx]%p 0 {tree.modify(1, idx1, 0)cnt--}if val%p 0 {tree.modify(1, idx1, val)cnt}nums[idx] valif tree.tr[1].g ! p {continue}if cnt n || n 6 {anscontinue}for i : 1; i n; i {leftG : tree.query(1, 1, i-1)rightG : tree.query(1, i1, n)if gcd(leftG, rightG) p {ansbreak}}}return ans}---复杂度- 时间复杂度O((n q) \times \log n)其中 n \le 6 时的暴力枚举是常数级。- 空间复杂度O(n)。