From 3084bbc18bdb9f044439d8cd63141ea830e876a9 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Sun, 14 Dec 2025 16:19:26 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.3777 --- .../README.md | 319 +++++++++++++++++- .../README_EN.md | 319 +++++++++++++++++- .../Solution.cpp | 64 ++++ .../Solution.go | 63 ++++ .../Solution.java | 71 ++++ .../Solution.py | 44 +++ .../Solution.ts | 62 ++++ 7 files changed, 934 insertions(+), 8 deletions(-) create mode 100644 solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.cpp create mode 100644 solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.go create mode 100644 solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.java create mode 100644 solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.py create mode 100644 solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.ts diff --git a/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/README.md b/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/README.md index 2a5b5d5e992af..1de24c9caa9ea 100644 --- a/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/README.md +++ b/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/README.md @@ -244,32 +244,343 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3700-3799/3777.Mi -### 方法一 +### 方法一:树状数组 + +我们可以将字符串 $s$ 转换为一个长度为 $n$ 的数组 $\textit{nums}$,其中 $\textit{nums}[0] = 0$,对于 $1 \leq i < n$,如果 $s[i] = s[i-1]$,则 $\textit{nums}[i] = 1$,否则 $\textit{nums}[i] = 0$。这样 $\textit{nums}[i]$ 表示在索引 $i$ 处是否存在相邻且相等的字符。那么我们计算区间 $[l, r]$ 内使子字符串 $s[l..r]$ 变成交替字符串所需的最小字符删除数就等价于计算 $\textit{nums}$ 数组在区间 $[l+1, r]$ 上的元素和。 + +为了高效地处理查询,我们可以使用树状数组来维护 $\textit{nums}$ 数组的前缀和。对于类型为 $[1, j]$ 的查询,我们需要将 $\textit{nums}[j]$ 和 $\textit{nums}[j+1]$(如果 $j+1 < n$)进行翻转,并更新树状数组。对于类型为 $[2, l, r]$ 的查询,我们可以通过树状数组快速计算区间 $[l+1, r]$ 上的元素和。 + +时间复杂度 $O((n + q) \log n)$,空间复杂度 $O(n)$。其中 $n$ 是字符串 $s$ 的长度,而 $q$ 是查询的数量。 #### Python3 ```python - +class BinaryIndexedTree: + __slots__ = "n", "c" + + def __init__(self, n: int): + self.n = n + self.c = [0] * (n + 1) + + def update(self, x: int, delta: int) -> None: + while x <= self.n: + self.c[x] += delta + x += x & -x + + def query(self, x: int) -> int: + s = 0 + while x: + s += self.c[x] + x -= x & -x + return s + + +class Solution: + def minDeletions(self, s: str, queries: List[List[int]]) -> List[int]: + n = len(s) + nums = [0] * n + bit = BinaryIndexedTree(n) + for i in range(1, n): + nums[i] = int(s[i] == s[i - 1]) + if nums[i]: + bit.update(i + 1, 1) + ans = [] + for q in queries: + if q[0] == 1: + j = q[1] + delta = (nums[j] ^ 1) - nums[j] + nums[j] ^= 1 + bit.update(j + 1, delta) + if j + 1 < n: + delta = (nums[j + 1] ^ 1) - nums[j + 1] + nums[j + 1] ^= 1 + bit.update(j + 2, delta) + else: + _, l, r = q + ans.append(bit.query(r + 1) - bit.query(l + 1)) + return ans ``` #### Java ```java - +class BinaryIndexedTree { + int n; + int[] c; + + BinaryIndexedTree(int n) { + this.n = n; + this.c = new int[n + 1]; + } + + void update(int x, int delta) { + while (x <= n) { + c[x] += delta; + x += x & -x; + } + } + + int query(int x) { + int s = 0; + while (x > 0) { + s += c[x]; + x -= x & -x; + } + return s; + } +} + +class Solution { + public int[] minDeletions(String s, int[][] queries) { + int n = s.length(); + int[] nums = new int[n]; + BinaryIndexedTree bit = new BinaryIndexedTree(n); + + for (int i = 1; i < n; i++) { + nums[i] = (s.charAt(i) == s.charAt(i - 1)) ? 1 : 0; + if (nums[i] == 1) { + bit.update(i + 1, 1); + } + } + + int cnt = 0; + for (int[] q : queries) { + if (q[0] == 2) { + cnt++; + } + } + + int[] ans = new int[cnt]; + int idx = 0; + + for (int[] q : queries) { + if (q[0] == 1) { + int j = q[1]; + + int delta = (nums[j] ^ 1) - nums[j]; + nums[j] ^= 1; + bit.update(j + 1, delta); + + if (j + 1 < n) { + delta = (nums[j + 1] ^ 1) - nums[j + 1]; + nums[j + 1] ^= 1; + bit.update(j + 2, delta); + } + } else { + int l = q[1]; + int r = q[2]; + ans[idx++] = bit.query(r + 1) - bit.query(l + 1); + } + } + return ans; + } +} ``` #### C++ ```cpp - +class BinaryIndexedTree { +public: + int n; + vector c; + + BinaryIndexedTree(int n) + : n(n) + , c(n + 1, 0) {} + + void update(int x, int delta) { + while (x <= n) { + c[x] += delta; + x += x & -x; + } + } + + int query(int x) { + int s = 0; + while (x > 0) { + s += c[x]; + x -= x & -x; + } + return s; + } +}; + +class Solution { +public: + vector minDeletions(string s, vector>& queries) { + int n = s.size(); + vector nums(n, 0); + BinaryIndexedTree bit(n); + + for (int i = 1; i < n; i++) { + nums[i] = (s[i] == s[i - 1]); + if (nums[i]) { + bit.update(i + 1, 1); + } + } + + vector ans; + + for (auto& q : queries) { + if (q[0] == 1) { + int j = q[1]; + + int delta = (nums[j] ^ 1) - nums[j]; + nums[j] ^= 1; + bit.update(j + 1, delta); + + if (j + 1 < n) { + delta = (nums[j + 1] ^ 1) - nums[j + 1]; + nums[j + 1] ^= 1; + bit.update(j + 2, delta); + } + } else { + int l = q[1]; + int r = q[2]; + ans.push_back(bit.query(r + 1) - bit.query(l + 1)); + } + } + return ans; + } +}; ``` #### Go ```go +type binaryIndexedTree struct { + n int + c []int +} + +func newBinaryIndexedTree(n int) *binaryIndexedTree { + return &binaryIndexedTree{ + n: n, + c: make([]int, n+1), + } +} + +func (bit *binaryIndexedTree) update(x, delta int) { + for x <= bit.n { + bit.c[x] += delta + x += x & -x + } +} + +func (bit *binaryIndexedTree) query(x int) int { + s := 0 + for x > 0 { + s += bit.c[x] + x -= x & -x + } + return s +} + +func minDeletions(s string, queries [][]int) []int { + n := len(s) + nums := make([]int, n) + bit := newBinaryIndexedTree(n) + + for i := 1; i < n; i++ { + if s[i] == s[i-1] { + nums[i] = 1 + bit.update(i+1, 1) + } + } + + ans := make([]int, 0) + + for _, q := range queries { + if q[0] == 1 { + j := q[1] + + delta := (nums[j] ^ 1 - nums[j]) + nums[j] ^= 1 + bit.update(j+1, delta) + + if j+1 < n { + delta = (nums[j+1] ^ 1 - nums[j+1]) + nums[j+1] ^= 1 + bit.update(j+2, delta) + } + } else { + l, r := q[1], q[2] + ans = append(ans, bit.query(r+1)-bit.query(l+1)) + } + } + + return ans +} +``` +#### TypeScript + +```ts +class BinaryIndexedTree { + n: number; + c: number[]; + + constructor(n: number) { + this.n = n; + this.c = Array(n + 1).fill(0); + } + + update(x: number, delta: number): void { + while (x <= this.n) { + this.c[x] += delta; + x += x & -x; + } + } + + query(x: number): number { + let s = 0; + while (x > 0) { + s += this.c[x]; + x -= x & -x; + } + return s; + } +} + +function minDeletions(s: string, queries: number[][]): number[] { + const n = s.length; + const nums: number[] = Array(n).fill(0); + const bit = new BinaryIndexedTree(n); + + for (let i = 1; i < n; i++) { + if (s[i] === s[i - 1]) { + nums[i] = 1; + bit.update(i + 1, 1); + } + } + + const ans: number[] = []; + + for (const q of queries) { + if (q[0] === 1) { + const j = q[1]; + + let delta = (nums[j] ^ 1) - nums[j]; + nums[j] ^= 1; + bit.update(j + 1, delta); + + if (j + 1 < n) { + delta = (nums[j + 1] ^ 1) - nums[j + 1]; + nums[j + 1] ^= 1; + bit.update(j + 2, delta); + } + } else { + const l = q[1], + r = q[2]; + ans.push(bit.query(r + 1) - bit.query(l + 1)); + } + } + + return ans; +} ``` diff --git a/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/README_EN.md b/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/README_EN.md index ba2de210ed38b..da0578a742ddb 100644 --- a/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/README_EN.md +++ b/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/README_EN.md @@ -241,32 +241,343 @@ A substring is a contiguous non-empty sequence of charac -### Solution 1 +### Solution 1: Binary Indexed Tree + +We can convert the string $s$ into an array $\textit{nums}$ of length $n$, where $\textit{nums}[0] = 0$, and for $1 \leq i < n$, if $s[i] = s[i-1]$, then $\textit{nums}[i] = 1$, otherwise $\textit{nums}[i] = 0$. This way $\textit{nums}[i]$ represents whether there are adjacent and equal characters at index $i$. Then calculating the minimum number of character deletions required to make the substring $s[l..r]$ an alternating string in the interval $[l, r]$ is equivalent to calculating the sum of elements in the $\textit{nums}$ array over the interval $[l+1, r]$. + +To handle queries efficiently, we can use a Binary Indexed Tree to maintain the prefix sum of the $\textit{nums}$ array. For queries of type $[1, j]$, we need to flip $\textit{nums}[j]$ and $\textit{nums}[j+1]$ (if $j+1 < n$), and update the Binary Indexed Tree. For queries of type $[2, l, r]$, we can quickly calculate the sum of elements over the interval $[l+1, r]$ through the Binary Indexed Tree. + +The time complexity is $O((n + q) \log n)$, and the space complexity is $O(n)$, where $n$ is the length of the string $s$, and $q$ is the number of queries. #### Python3 ```python - +class BinaryIndexedTree: + __slots__ = "n", "c" + + def __init__(self, n: int): + self.n = n + self.c = [0] * (n + 1) + + def update(self, x: int, delta: int) -> None: + while x <= self.n: + self.c[x] += delta + x += x & -x + + def query(self, x: int) -> int: + s = 0 + while x: + s += self.c[x] + x -= x & -x + return s + + +class Solution: + def minDeletions(self, s: str, queries: List[List[int]]) -> List[int]: + n = len(s) + nums = [0] * n + bit = BinaryIndexedTree(n) + for i in range(1, n): + nums[i] = int(s[i] == s[i - 1]) + if nums[i]: + bit.update(i + 1, 1) + ans = [] + for q in queries: + if q[0] == 1: + j = q[1] + delta = (nums[j] ^ 1) - nums[j] + nums[j] ^= 1 + bit.update(j + 1, delta) + if j + 1 < n: + delta = (nums[j + 1] ^ 1) - nums[j + 1] + nums[j + 1] ^= 1 + bit.update(j + 2, delta) + else: + _, l, r = q + ans.append(bit.query(r + 1) - bit.query(l + 1)) + return ans ``` #### Java ```java - +class BinaryIndexedTree { + int n; + int[] c; + + BinaryIndexedTree(int n) { + this.n = n; + this.c = new int[n + 1]; + } + + void update(int x, int delta) { + while (x <= n) { + c[x] += delta; + x += x & -x; + } + } + + int query(int x) { + int s = 0; + while (x > 0) { + s += c[x]; + x -= x & -x; + } + return s; + } +} + +class Solution { + public int[] minDeletions(String s, int[][] queries) { + int n = s.length(); + int[] nums = new int[n]; + BinaryIndexedTree bit = new BinaryIndexedTree(n); + + for (int i = 1; i < n; i++) { + nums[i] = (s.charAt(i) == s.charAt(i - 1)) ? 1 : 0; + if (nums[i] == 1) { + bit.update(i + 1, 1); + } + } + + int cnt = 0; + for (int[] q : queries) { + if (q[0] == 2) { + cnt++; + } + } + + int[] ans = new int[cnt]; + int idx = 0; + + for (int[] q : queries) { + if (q[0] == 1) { + int j = q[1]; + + int delta = (nums[j] ^ 1) - nums[j]; + nums[j] ^= 1; + bit.update(j + 1, delta); + + if (j + 1 < n) { + delta = (nums[j + 1] ^ 1) - nums[j + 1]; + nums[j + 1] ^= 1; + bit.update(j + 2, delta); + } + } else { + int l = q[1]; + int r = q[2]; + ans[idx++] = bit.query(r + 1) - bit.query(l + 1); + } + } + return ans; + } +} ``` #### C++ ```cpp - +class BinaryIndexedTree { +public: + int n; + vector c; + + BinaryIndexedTree(int n) + : n(n) + , c(n + 1, 0) {} + + void update(int x, int delta) { + while (x <= n) { + c[x] += delta; + x += x & -x; + } + } + + int query(int x) { + int s = 0; + while (x > 0) { + s += c[x]; + x -= x & -x; + } + return s; + } +}; + +class Solution { +public: + vector minDeletions(string s, vector>& queries) { + int n = s.size(); + vector nums(n, 0); + BinaryIndexedTree bit(n); + + for (int i = 1; i < n; i++) { + nums[i] = (s[i] == s[i - 1]); + if (nums[i]) { + bit.update(i + 1, 1); + } + } + + vector ans; + + for (auto& q : queries) { + if (q[0] == 1) { + int j = q[1]; + + int delta = (nums[j] ^ 1) - nums[j]; + nums[j] ^= 1; + bit.update(j + 1, delta); + + if (j + 1 < n) { + delta = (nums[j + 1] ^ 1) - nums[j + 1]; + nums[j + 1] ^= 1; + bit.update(j + 2, delta); + } + } else { + int l = q[1]; + int r = q[2]; + ans.push_back(bit.query(r + 1) - bit.query(l + 1)); + } + } + return ans; + } +}; ``` #### Go ```go +type binaryIndexedTree struct { + n int + c []int +} + +func newBinaryIndexedTree(n int) *binaryIndexedTree { + return &binaryIndexedTree{ + n: n, + c: make([]int, n+1), + } +} + +func (bit *binaryIndexedTree) update(x, delta int) { + for x <= bit.n { + bit.c[x] += delta + x += x & -x + } +} + +func (bit *binaryIndexedTree) query(x int) int { + s := 0 + for x > 0 { + s += bit.c[x] + x -= x & -x + } + return s +} + +func minDeletions(s string, queries [][]int) []int { + n := len(s) + nums := make([]int, n) + bit := newBinaryIndexedTree(n) + + for i := 1; i < n; i++ { + if s[i] == s[i-1] { + nums[i] = 1 + bit.update(i+1, 1) + } + } + + ans := make([]int, 0) + + for _, q := range queries { + if q[0] == 1 { + j := q[1] + + delta := (nums[j] ^ 1 - nums[j]) + nums[j] ^= 1 + bit.update(j+1, delta) + + if j+1 < n { + delta = (nums[j+1] ^ 1 - nums[j+1]) + nums[j+1] ^= 1 + bit.update(j+2, delta) + } + } else { + l, r := q[1], q[2] + ans = append(ans, bit.query(r+1)-bit.query(l+1)) + } + } + + return ans +} +``` +#### TypeScript + +```ts +class BinaryIndexedTree { + n: number; + c: number[]; + + constructor(n: number) { + this.n = n; + this.c = Array(n + 1).fill(0); + } + + update(x: number, delta: number): void { + while (x <= this.n) { + this.c[x] += delta; + x += x & -x; + } + } + + query(x: number): number { + let s = 0; + while (x > 0) { + s += this.c[x]; + x -= x & -x; + } + return s; + } +} + +function minDeletions(s: string, queries: number[][]): number[] { + const n = s.length; + const nums: number[] = Array(n).fill(0); + const bit = new BinaryIndexedTree(n); + + for (let i = 1; i < n; i++) { + if (s[i] === s[i - 1]) { + nums[i] = 1; + bit.update(i + 1, 1); + } + } + + const ans: number[] = []; + + for (const q of queries) { + if (q[0] === 1) { + const j = q[1]; + + let delta = (nums[j] ^ 1) - nums[j]; + nums[j] ^= 1; + bit.update(j + 1, delta); + + if (j + 1 < n) { + delta = (nums[j + 1] ^ 1) - nums[j + 1]; + nums[j + 1] ^= 1; + bit.update(j + 2, delta); + } + } else { + const l = q[1], + r = q[2]; + ans.push(bit.query(r + 1) - bit.query(l + 1)); + } + } + + return ans; +} ``` diff --git a/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.cpp b/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.cpp new file mode 100644 index 0000000000000..dc8c91885fa8c --- /dev/null +++ b/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.cpp @@ -0,0 +1,64 @@ +class BinaryIndexedTree { +public: + int n; + vector c; + + BinaryIndexedTree(int n) + : n(n) + , c(n + 1, 0) {} + + void update(int x, int delta) { + while (x <= n) { + c[x] += delta; + x += x & -x; + } + } + + int query(int x) { + int s = 0; + while (x > 0) { + s += c[x]; + x -= x & -x; + } + return s; + } +}; + +class Solution { +public: + vector minDeletions(string s, vector>& queries) { + int n = s.size(); + vector nums(n, 0); + BinaryIndexedTree bit(n); + + for (int i = 1; i < n; i++) { + nums[i] = (s[i] == s[i - 1]); + if (nums[i]) { + bit.update(i + 1, 1); + } + } + + vector ans; + + for (auto& q : queries) { + if (q[0] == 1) { + int j = q[1]; + + int delta = (nums[j] ^ 1) - nums[j]; + nums[j] ^= 1; + bit.update(j + 1, delta); + + if (j + 1 < n) { + delta = (nums[j + 1] ^ 1) - nums[j + 1]; + nums[j + 1] ^= 1; + bit.update(j + 2, delta); + } + } else { + int l = q[1]; + int r = q[2]; + ans.push_back(bit.query(r + 1) - bit.query(l + 1)); + } + } + return ans; + } +}; diff --git a/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.go b/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.go new file mode 100644 index 0000000000000..6851b5289668a --- /dev/null +++ b/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.go @@ -0,0 +1,63 @@ +type binaryIndexedTree struct { + n int + c []int +} + +func newBinaryIndexedTree(n int) *binaryIndexedTree { + return &binaryIndexedTree{ + n: n, + c: make([]int, n+1), + } +} + +func (bit *binaryIndexedTree) update(x, delta int) { + for x <= bit.n { + bit.c[x] += delta + x += x & -x + } +} + +func (bit *binaryIndexedTree) query(x int) int { + s := 0 + for x > 0 { + s += bit.c[x] + x -= x & -x + } + return s +} + +func minDeletions(s string, queries [][]int) []int { + n := len(s) + nums := make([]int, n) + bit := newBinaryIndexedTree(n) + + for i := 1; i < n; i++ { + if s[i] == s[i-1] { + nums[i] = 1 + bit.update(i+1, 1) + } + } + + ans := make([]int, 0) + + for _, q := range queries { + if q[0] == 1 { + j := q[1] + + delta := (nums[j] ^ 1 - nums[j]) + nums[j] ^= 1 + bit.update(j+1, delta) + + if j+1 < n { + delta = (nums[j+1] ^ 1 - nums[j+1]) + nums[j+1] ^= 1 + bit.update(j+2, delta) + } + } else { + l, r := q[1], q[2] + ans = append(ans, bit.query(r+1)-bit.query(l+1)) + } + } + + return ans +} diff --git a/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.java b/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.java new file mode 100644 index 0000000000000..6607a6be74f89 --- /dev/null +++ b/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.java @@ -0,0 +1,71 @@ +class BinaryIndexedTree { + int n; + int[] c; + + BinaryIndexedTree(int n) { + this.n = n; + this.c = new int[n + 1]; + } + + void update(int x, int delta) { + while (x <= n) { + c[x] += delta; + x += x & -x; + } + } + + int query(int x) { + int s = 0; + while (x > 0) { + s += c[x]; + x -= x & -x; + } + return s; + } +} + +class Solution { + public int[] minDeletions(String s, int[][] queries) { + int n = s.length(); + int[] nums = new int[n]; + BinaryIndexedTree bit = new BinaryIndexedTree(n); + + for (int i = 1; i < n; i++) { + nums[i] = (s.charAt(i) == s.charAt(i - 1)) ? 1 : 0; + if (nums[i] == 1) { + bit.update(i + 1, 1); + } + } + + int cnt = 0; + for (int[] q : queries) { + if (q[0] == 2) { + cnt++; + } + } + + int[] ans = new int[cnt]; + int idx = 0; + + for (int[] q : queries) { + if (q[0] == 1) { + int j = q[1]; + + int delta = (nums[j] ^ 1) - nums[j]; + nums[j] ^= 1; + bit.update(j + 1, delta); + + if (j + 1 < n) { + delta = (nums[j + 1] ^ 1) - nums[j + 1]; + nums[j + 1] ^= 1; + bit.update(j + 2, delta); + } + } else { + int l = q[1]; + int r = q[2]; + ans[idx++] = bit.query(r + 1) - bit.query(l + 1); + } + } + return ans; + } +} diff --git a/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.py b/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.py new file mode 100644 index 0000000000000..558197d3aaae2 --- /dev/null +++ b/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.py @@ -0,0 +1,44 @@ +class BinaryIndexedTree: + __slots__ = "n", "c" + + def __init__(self, n: int): + self.n = n + self.c = [0] * (n + 1) + + def update(self, x: int, delta: int) -> None: + while x <= self.n: + self.c[x] += delta + x += x & -x + + def query(self, x: int) -> int: + s = 0 + while x: + s += self.c[x] + x -= x & -x + return s + + +class Solution: + def minDeletions(self, s: str, queries: List[List[int]]) -> List[int]: + n = len(s) + nums = [0] * n + bit = BinaryIndexedTree(n) + for i in range(1, n): + nums[i] = int(s[i] == s[i - 1]) + if nums[i]: + bit.update(i + 1, 1) + ans = [] + for q in queries: + if q[0] == 1: + j = q[1] + delta = (nums[j] ^ 1) - nums[j] + nums[j] ^= 1 + bit.update(j + 1, delta) + if j + 1 < n: + delta = (nums[j + 1] ^ 1) - nums[j + 1] + nums[j + 1] ^= 1 + bit.update(j + 2, delta) + else: + _, l, r = q + ans.append(bit.query(r + 1) - bit.query(l + 1)) + return ans diff --git a/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.ts b/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.ts new file mode 100644 index 0000000000000..cbd3b18efca88 --- /dev/null +++ b/solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/Solution.ts @@ -0,0 +1,62 @@ +class BinaryIndexedTree { + n: number; + c: number[]; + + constructor(n: number) { + this.n = n; + this.c = Array(n + 1).fill(0); + } + + update(x: number, delta: number): void { + while (x <= this.n) { + this.c[x] += delta; + x += x & -x; + } + } + + query(x: number): number { + let s = 0; + while (x > 0) { + s += this.c[x]; + x -= x & -x; + } + return s; + } +} + +function minDeletions(s: string, queries: number[][]): number[] { + const n = s.length; + const nums: number[] = Array(n).fill(0); + const bit = new BinaryIndexedTree(n); + + for (let i = 1; i < n; i++) { + if (s[i] === s[i - 1]) { + nums[i] = 1; + bit.update(i + 1, 1); + } + } + + const ans: number[] = []; + + for (const q of queries) { + if (q[0] === 1) { + const j = q[1]; + + let delta = (nums[j] ^ 1) - nums[j]; + nums[j] ^= 1; + bit.update(j + 1, delta); + + if (j + 1 < n) { + delta = (nums[j + 1] ^ 1) - nums[j + 1]; + nums[j + 1] ^= 1; + bit.update(j + 2, delta); + } + } else { + const l = q[1], + r = q[2]; + ans.push(bit.query(r + 1) - bit.query(l + 1)); + } + } + + return ans; +}