# 区间 [L,R] 内的数都加上 v o,l,r=1,1,n defupdate(o: int, l: int, r: int, L: int, R: int, v: int) -> None: if L <= l and r <= R: do(o, v) return spread(o) m = (l + r) // 2 if m >= L: update(o * 2, l, m, L, R, v) if m < R: update(o * 2 + 1, m + 1, r, L, R, v) mn[o] = min(mn[o * 2], mn[o * 2 + 1])
# 查询区间 [L,R] 的最小值 o,l,r=1,1,n defquery(o: int, l: int, r: int, L: int, R: int) -> int: if L <= l and r <= R: return mn[o] spread(o) m = (l + r) // 2 if m >= R: return query(o * 2, l, m, L, R) if m < L: return query(o * 2 + 1, m + 1, r, L, R) returnmin(query(o * 2, l, m, L, R), query(o * 2 + 1, m + 1, r, L, R))
ans = 0 last = [0] * n last2 = [0] * n for i, x inenumerate(nums, 1): update(1, 1, n, i, i, ans) # 相当于设置 f[i+1] 的值 update(1, 1, n, last[x] + 1, i, -1) if last[x]: update(1, 1, n, last2[x] + 1, last[x], 1) ans = k + query(1, 1, n, 1, i) last2[x] = last[x] last[x] = i return ans + n
classSolution { voiddo_(int o, int v){ mn[o] += v; todo[o] += v; }
voidspread(int o){ int v = todo[o]; if (v) { do_(o * 2, v); do_(o * 2 + 1, v); todo[o] = 0; } }
// 区间 [L,R] 内的数都加上 v o,l,r=1,1,n voidupdate(int o, int l, int r, int L, int R, int v){ if (L <= l && r <= R) { do_(o, v); return; } spread(o); int m = (l + r) / 2; if (m >= L) update(o * 2, l, m, L, R, v); if (m < R) update(o * 2 + 1, m + 1, r, L, R, v); mn[o] = min(mn[o * 2], mn[o * 2 + 1]); }
// 查询区间 [L,R] 的最小值 o,l,r=1,1,n intquery(int o, int l, int r, int L, int R){ if (L <= l && r <= R) return mn[o]; spread(o); int m = (l + r) / 2; if (m >= R) returnquery(o * 2, l, m, L, R); if (m < L) returnquery(o * 2 + 1, m + 1, r, L, R); returnmin(query(o * 2, l, m, L, R), query(o * 2 + 1, m + 1, r, L, R)); }
public: intminCost(vector<int> &nums, int k){ int n = nums.size(), ans = 0; memset(mn, 0, sizeof(int) * 4 * n); memset(todo, 0, sizeof(int) * 4 * n); memset(last, 0, sizeof(int) * n); memset(last2, 0, sizeof(int) * n); for (int i = 1; i <= n; ++i) { int x = nums[i - 1]; update(1, 1, n, i, i, ans); // 相当于设置 f[i+1] 的值 update(1, 1, n, last[x] + 1, i, -1); if (last[x]) update(1, 1, n, last2[x] + 1, last[x], 1); ans = k + query(1, 1, n, 1, i); last2[x] = last[x]; last[x] = i; } return ans + n; } };
// Lazy 线段树模板(区间加,查询区间最小) type seg []struct{ l, r, min, todo int }
func(t seg) build(o, l, r int) { t[o].l, t[o].r = l, r if l == r { return } m := (l + r) >> 1 t.build(o<<1, l, m) t.build(o<<1|1, m+1, r) }
func(t seg) do(o, v int) { t[o].min += v t[o].todo += v }
func(t seg) spread(o int) { if v := t[o].todo; v != 0 { t.do(o<<1, v) t.do(o<<1|1, v) t[o].todo = 0 } }
// 区间 [l,r] 内的数都加上 v o=1 func(t seg) update(o, l, r, v int) { if l <= t[o].l && t[o].r <= r { t.do(o, v) return } t.spread(o) m := (t[o].l + t[o].r) >> 1 if l <= m { t.update(o<<1, l, r, v) } if m < r { t.update(o<<1|1, l, r, v) } t[o].min = min(t[o<<1].min, t[o<<1|1].min) }
// 查询区间 [l,r] 的最小值 o=1 func(t seg) query(o, l, r int) int { if l <= t[o].l && t[o].r <= r { return t[o].min } t.spread(o) m := (t[o].l + t[o].r) >> 1 if r <= m { return t.query(o<<1, l, r) } if l > m { return t.query(o<<1|1, l, r) } return min(t.query(o<<1, l, r), t.query(o<<1|1, l, r)) }
funcminCost(nums []int, k int) (ans int) { n := len(nums) last := make([]int, n) last2 := make([]int, n) t := make(seg, n*4) t.build(1, 1, n) for i, x := range nums { i++ // 线段树区间从 1 开始 t.update(1, i, i, ans) // 相当于设置 f[i+1] 的值 t.update(1, last[x]+1, i, -1) if last[x] > 0 { t.update(1, last2[x]+1, last[x], 1) } ans = k + t.query(1, 1, i) last2[x] = last[x] last[x] = i } return ans + n }
funcmin(a, b int)int { if a > b { return b }; return a }