diff --git a/src/main/java/g3101_3200/s3163_string_compression_iii/Solution.java b/src/main/java/g3101_3200/s3163_string_compression_iii/Solution.java
new file mode 100644
index 000000000..f1f7e3dac
--- /dev/null
+++ b/src/main/java/g3101_3200/s3163_string_compression_iii/Solution.java
@@ -0,0 +1,26 @@
+package g3101_3200.s3163_string_compression_iii;
+
+// #Medium #String #2024_06_02_Time_17_ms_(88.10%)_Space_45.7_MB_(71.08%)
+
+public class Solution {
+ public String compressedString(String word) {
+ StringBuilder builder = new StringBuilder();
+ char last = word.charAt(0);
+ int count = 1;
+ for (int i = 1, l = word.length(); i < l; i++) {
+ if (word.charAt(i) == last) {
+ count++;
+ if (count == 10) {
+ builder.append(9).append(last);
+ count = 1;
+ }
+ } else {
+ builder.append(count).append(last);
+ last = word.charAt(i);
+ count = 1;
+ }
+ }
+ builder.append(count).append(last);
+ return builder.toString();
+ }
+}
diff --git a/src/main/java/g3101_3200/s3163_string_compression_iii/readme.md b/src/main/java/g3101_3200/s3163_string_compression_iii/readme.md
new file mode 100644
index 000000000..05221f34f
--- /dev/null
+++ b/src/main/java/g3101_3200/s3163_string_compression_iii/readme.md
@@ -0,0 +1,42 @@
+3163\. String Compression III
+
+Medium
+
+Given a string `word`, compress it using the following algorithm:
+
+* Begin with an empty string `comp`. While `word` is **not** empty, use the following operation:
+ * Remove a maximum length prefix of `word` made of a _single character_ `c` repeating **at most** 9 times.
+ * Append the length of the prefix followed by `c` to `comp`.
+
+Return the string `comp`.
+
+**Example 1:**
+
+**Input:** word = "abcde"
+
+**Output:** "1a1b1c1d1e"
+
+**Explanation:**
+
+Initially, `comp = ""`. Apply the operation 5 times, choosing `"a"`, `"b"`, `"c"`, `"d"`, and `"e"` as the prefix in each operation.
+
+For each prefix, append `"1"` followed by the character to `comp`.
+
+**Example 2:**
+
+**Input:** word = "aaaaaaaaaaaaaabb"
+
+**Output:** "9a5a2b"
+
+**Explanation:**
+
+Initially, `comp = ""`. Apply the operation 3 times, choosing `"aaaaaaaaa"`, `"aaaaa"`, and `"bb"` as the prefix in each operation.
+
+* For prefix `"aaaaaaaaa"`, append `"9"` followed by `"a"` to `comp`.
+* For prefix `"aaaaa"`, append `"5"` followed by `"a"` to `comp`.
+* For prefix `"bb"`, append `"2"` followed by `"b"` to `comp`.
+
+**Constraints:**
+
+* 1 <= word.length <= 2 * 105
+* `word` consists only of lowercase English letters.
\ No newline at end of file
diff --git a/src/main/java/g3101_3200/s3164_find_the_number_of_good_pairs_ii/Solution.java b/src/main/java/g3101_3200/s3164_find_the_number_of_good_pairs_ii/Solution.java
new file mode 100644
index 000000000..eab02544a
--- /dev/null
+++ b/src/main/java/g3101_3200/s3164_find_the_number_of_good_pairs_ii/Solution.java
@@ -0,0 +1,34 @@
+package g3101_3200.s3164_find_the_number_of_good_pairs_ii;
+
+// #Medium #Array #Hash_Table #2024_06_02_Time_407_ms_(75.28%)_Space_66.8_MB_(7.30%)
+
+import java.util.HashMap;
+
+public class Solution {
+ public long numberOfPairs(int[] nums1, int[] nums2, int k) {
+ HashMap hm = new HashMap<>();
+ long ans = 0;
+ for (int val : nums2) {
+ hm.put(val * k, hm.getOrDefault(val * k, 0) + 1);
+ }
+ for (int indx = 0; indx < nums1.length; indx++) {
+ if (nums1[indx] % k != 0) {
+ continue;
+ }
+ for (int factor = 1; factor * factor <= nums1[indx]; factor++) {
+ if (nums1[indx] % factor != 0) {
+ continue;
+ }
+ int factor1 = factor;
+ int factor2 = nums1[indx] / factor;
+ if (hm.containsKey(factor1)) {
+ ans += hm.get(factor1);
+ }
+ if (factor1 != factor2 && hm.containsKey(factor2)) {
+ ans += hm.get(factor2);
+ }
+ }
+ }
+ return ans;
+ }
+}
diff --git a/src/main/java/g3101_3200/s3164_find_the_number_of_good_pairs_ii/readme.md b/src/main/java/g3101_3200/s3164_find_the_number_of_good_pairs_ii/readme.md
new file mode 100644
index 000000000..49c337b3d
--- /dev/null
+++ b/src/main/java/g3101_3200/s3164_find_the_number_of_good_pairs_ii/readme.md
@@ -0,0 +1,35 @@
+3164\. Find the Number of Good Pairs II
+
+Medium
+
+You are given 2 integer arrays `nums1` and `nums2` of lengths `n` and `m` respectively. You are also given a **positive** integer `k`.
+
+A pair `(i, j)` is called **good** if `nums1[i]` is divisible by `nums2[j] * k` (`0 <= i <= n - 1`, `0 <= j <= m - 1`).
+
+Return the total number of **good** pairs.
+
+**Example 1:**
+
+**Input:** nums1 = [1,3,4], nums2 = [1,3,4], k = 1
+
+**Output:** 5
+
+**Explanation:**
+
+The 5 good pairs are `(0, 0)`, `(1, 0)`, `(1, 1)`, `(2, 0)`, and `(2, 2)`.
+
+**Example 2:**
+
+**Input:** nums1 = [1,2,4,12], nums2 = [2,4], k = 3
+
+**Output:** 2
+
+**Explanation:**
+
+The 2 good pairs are `(3, 0)` and `(3, 1)`.
+
+**Constraints:**
+
+* 1 <= n, m <= 105
+* 1 <= nums1[i], nums2[j] <= 106
+* 1 <= k <= 103
\ No newline at end of file
diff --git a/src/main/java/g3101_3200/s3165_maximum_sum_of_subsequence_with_non_adjacent_elements/Solution.java b/src/main/java/g3101_3200/s3165_maximum_sum_of_subsequence_with_non_adjacent_elements/Solution.java
new file mode 100644
index 000000000..8de741c4b
--- /dev/null
+++ b/src/main/java/g3101_3200/s3165_maximum_sum_of_subsequence_with_non_adjacent_elements/Solution.java
@@ -0,0 +1,125 @@
+package g3101_3200.s3165_maximum_sum_of_subsequence_with_non_adjacent_elements;
+
+// #Hard #Array #Dynamic_Programming #Divide_and_Conquer #Segment_Tree
+// #2024_06_02_Time_1927_ms_(87.75%)_Space_82.1_MB_(5.31%)
+
+import java.util.stream.Stream;
+
+public class Solution {
+ private static final int MOD = 1_000_000_007;
+
+ public int maximumSumSubsequence(int[] nums, int[][] queries) {
+ int ans = 0;
+ SegTree segTree = new SegTree(nums);
+ for (int[] q : queries) {
+ int idx = q[0];
+ int val = q[1];
+ segTree.update(idx, val);
+ ans = (ans + segTree.getMax()) % MOD;
+ }
+ return ans;
+ }
+
+ static class SegTree {
+ private static class Record {
+ int takeFirstTakeLast;
+ int takeFirstSkipLast;
+ int skipFirstSkipLast;
+ int skipFirstTakeLast;
+
+ public Integer getMax() {
+ return Stream.of(
+ this.takeFirstSkipLast,
+ this.takeFirstTakeLast,
+ this.skipFirstSkipLast,
+ this.skipFirstTakeLast)
+ .max(Integer::compare)
+ .orElse(null);
+ }
+
+ public Integer skipLast() {
+ return Stream.of(this.takeFirstSkipLast, this.skipFirstSkipLast)
+ .max(Integer::compare)
+ .orElse(null);
+ }
+
+ public Integer takeLast() {
+ return Stream.of(this.skipFirstTakeLast, this.takeFirstTakeLast)
+ .max(Integer::compare)
+ .orElse(null);
+ }
+ }
+
+ private final Record[] seg;
+ private final int[] nums;
+
+ public SegTree(int[] nums) {
+ this.nums = nums;
+ seg = new Record[4 * nums.length];
+ for (int i = 0; i < 4 * nums.length; ++i) {
+ seg[i] = new Record();
+ }
+ build(0, nums.length - 1, 0);
+ }
+
+ private void build(int i, int j, int k) {
+ if (i == j) {
+ seg[k].takeFirstTakeLast = nums[i];
+ return;
+ }
+ int mid = (i + j) >> 1;
+ build(i, mid, 2 * k + 1);
+ build(mid + 1, j, 2 * k + 2);
+ merge(k);
+ }
+
+ // merge [2*k+1, 2*k+2] into k
+ private void merge(int k) {
+ seg[k].takeFirstSkipLast =
+ Math.max(
+ seg[2 * k + 1].takeFirstSkipLast + seg[2 * k + 2].skipLast(),
+ seg[2 * k + 1].takeFirstTakeLast + seg[2 * k + 2].skipFirstSkipLast);
+
+ seg[k].takeFirstTakeLast =
+ Math.max(
+ seg[2 * k + 1].takeFirstSkipLast + seg[2 * k + 2].takeLast(),
+ seg[2 * k + 1].takeFirstTakeLast + seg[2 * k + 2].skipFirstTakeLast);
+
+ seg[k].skipFirstTakeLast =
+ Math.max(
+ seg[2 * k + 1].skipFirstSkipLast + seg[2 * k + 2].takeLast(),
+ seg[2 * k + 1].skipFirstTakeLast + seg[2 * k + 2].skipFirstTakeLast);
+
+ seg[k].skipFirstSkipLast =
+ Math.max(
+ seg[2 * k + 1].skipFirstSkipLast + seg[2 * k + 2].skipLast(),
+ seg[2 * k + 1].skipFirstTakeLast + seg[2 * k + 2].skipFirstSkipLast);
+ }
+
+ // child -> parent
+ public void update(int idx, int val) {
+ int i = 0;
+ int j = nums.length - 1;
+ int k = 0;
+ update(idx, val, k, i, j);
+ }
+
+ private void update(int idx, int val, int k, int i, int j) {
+ if (i == j) {
+ seg[k].takeFirstTakeLast = val;
+ return;
+ }
+ int mid = (i + j) >> 1;
+ if (idx <= mid) {
+ update(idx, val, 2 * k + 1, i, mid);
+ } else {
+ update(idx, val, 2 * k + 2, mid + 1, j);
+ }
+ merge(k);
+ }
+
+ public int getMax() {
+ return seg[0].getMax();
+ }
+ }
+}
diff --git a/src/main/java/g3101_3200/s3165_maximum_sum_of_subsequence_with_non_adjacent_elements/readme.md b/src/main/java/g3101_3200/s3165_maximum_sum_of_subsequence_with_non_adjacent_elements/readme.md
new file mode 100644
index 000000000..b02f63314
--- /dev/null
+++ b/src/main/java/g3101_3200/s3165_maximum_sum_of_subsequence_with_non_adjacent_elements/readme.md
@@ -0,0 +1,41 @@
+3165\. Maximum Sum of Subsequence With Non-adjacent Elements
+
+Hard
+
+You are given an array `nums` consisting of integers. You are also given a 2D array `queries`, where queries[i] = [posi, xi]
.
+
+For query `i`, we first set nums[posi]
equal to xi
, then we calculate the answer to query `i` which is the **maximum** sum of a subsequence of `nums` where **no two adjacent elements are selected**.
+
+Return the _sum_ of the answers to all queries.
+
+Since the final answer may be very large, return it **modulo** 109 + 7
.
+
+A **subsequence** is an array that can be derived from another array by deleting some or no elements without changing the order of the remaining elements.
+
+**Example 1:**
+
+**Input:** nums = [3,5,9], queries = [[1,-2],[0,-3]]
+
+**Output:** 21
+
+**Explanation:**
+ After the 1st query, `nums = [3,-2,9]` and the maximum sum of a subsequence with non-adjacent elements is `3 + 9 = 12`.
+ After the 2nd query, `nums = [-3,-2,9]` and the maximum sum of a subsequence with non-adjacent elements is 9.
+
+**Example 2:**
+
+**Input:** nums = [0,-1], queries = [[0,-5]]
+
+**Output:** 0
+
+**Explanation:**
+ After the 1st query, `nums = [-5,-1]` and the maximum sum of a subsequence with non-adjacent elements is 0 (choosing an empty subsequence).
+
+**Constraints:**
+
+* 1 <= nums.length <= 5 * 104
+* -105 <= nums[i] <= 105
+* 1 <= queries.length <= 5 * 104
+* queries[i] == [posi, xi]
+* 0 <= posi <= nums.length - 1
+* -105 <= xi <= 105
\ No newline at end of file
diff --git a/src/test/java/g3101_3200/s3163_string_compression_iii/SolutionTest.java b/src/test/java/g3101_3200/s3163_string_compression_iii/SolutionTest.java
new file mode 100644
index 000000000..3ba5d937b
--- /dev/null
+++ b/src/test/java/g3101_3200/s3163_string_compression_iii/SolutionTest.java
@@ -0,0 +1,18 @@
+package g3101_3200.s3163_string_compression_iii;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+class SolutionTest {
+ @Test
+ void compressedString() {
+ assertThat(new Solution().compressedString("abcde"), equalTo("1a1b1c1d1e"));
+ }
+
+ @Test
+ void compressedString2() {
+ assertThat(new Solution().compressedString("aaaaaaaaaaaaaabb"), equalTo("9a5a2b"));
+ }
+}
diff --git a/src/test/java/g3101_3200/s3164_find_the_number_of_good_pairs_ii/SolutionTest.java b/src/test/java/g3101_3200/s3164_find_the_number_of_good_pairs_ii/SolutionTest.java
new file mode 100644
index 000000000..b7d7f3e90
--- /dev/null
+++ b/src/test/java/g3101_3200/s3164_find_the_number_of_good_pairs_ii/SolutionTest.java
@@ -0,0 +1,22 @@
+package g3101_3200.s3164_find_the_number_of_good_pairs_ii;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+class SolutionTest {
+ @Test
+ void numberOfPairs() {
+ assertThat(
+ new Solution().numberOfPairs(new int[] {1, 3, 4}, new int[] {1, 3, 4}, 1),
+ equalTo(5L));
+ }
+
+ @Test
+ void numberOfPairs2() {
+ assertThat(
+ new Solution().numberOfPairs(new int[] {1, 2, 4, 12}, new int[] {2, 4}, 3),
+ equalTo(2L));
+ }
+}
diff --git a/src/test/java/g3101_3200/s3165_maximum_sum_of_subsequence_with_non_adjacent_elements/SolutionTest.java b/src/test/java/g3101_3200/s3165_maximum_sum_of_subsequence_with_non_adjacent_elements/SolutionTest.java
new file mode 100644
index 000000000..d84433a92
--- /dev/null
+++ b/src/test/java/g3101_3200/s3165_maximum_sum_of_subsequence_with_non_adjacent_elements/SolutionTest.java
@@ -0,0 +1,23 @@
+package g3101_3200.s3165_maximum_sum_of_subsequence_with_non_adjacent_elements;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+class SolutionTest {
+ @Test
+ void maximumSumSubsequence() {
+ assertThat(
+ new Solution()
+ .maximumSumSubsequence(new int[] {3, 5, 9}, new int[][] {{1, -2}, {0, -3}}),
+ equalTo(21));
+ }
+
+ @Test
+ void maximumSumSubsequence2() {
+ assertThat(
+ new Solution().maximumSumSubsequence(new int[] {0, -1}, new int[][] {{0, -5}}),
+ equalTo(0));
+ }
+}