diff --git a/build.gradle b/build.gradle
index 767829e41..7081e1e5d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -12,10 +12,10 @@ repositories {
}
dependencies {
- testImplementation 'org.junit.jupiter:junit-jupiter:[5.11.3,)'
+ testImplementation 'org.junit.jupiter:junit-jupiter:[5.12.0,)'
testImplementation 'org.hamcrest:hamcrest-core:[3.0,)'
- testImplementation 'org.zapodot:embedded-db-junit-jupiter:[2.2.0,)'
- testRuntimeOnly 'org.junit.platform:junit-platform-launcher:[1.11.3,)'
+ testImplementation 'org.zapodot:embedded-db-junit-jupiter:2.2.0'
+ testRuntimeOnly 'org.junit.platform:junit-platform-launcher:[1.12.0,)'
}
test {
diff --git a/src/main/java/g3401_3500/s3498_reverse_degree_of_a_string/Solution.java b/src/main/java/g3401_3500/s3498_reverse_degree_of_a_string/Solution.java
new file mode 100644
index 000000000..230da748a
--- /dev/null
+++ b/src/main/java/g3401_3500/s3498_reverse_degree_of_a_string/Solution.java
@@ -0,0 +1,13 @@
+package g3401_3500.s3498_reverse_degree_of_a_string;
+
+// #Easy #String #Simulation #2025_04_01_Time_1_ms_(100.00%)_Space_42.64_MB_(92.21%)
+
+public class Solution {
+ public int reverseDegree(String s) {
+ int ans = 0;
+ for (int i = 0; i < s.length(); ++i) {
+ ans += (26 - (s.charAt(i) - 'a')) * (i + 1);
+ }
+ return ans;
+ }
+}
diff --git a/src/main/java/g3401_3500/s3498_reverse_degree_of_a_string/readme.md b/src/main/java/g3401_3500/s3498_reverse_degree_of_a_string/readme.md
new file mode 100644
index 000000000..d8837fcd3
--- /dev/null
+++ b/src/main/java/g3401_3500/s3498_reverse_degree_of_a_string/readme.md
@@ -0,0 +1,50 @@
+3498\. Reverse Degree of a String
+
+Easy
+
+Given a string `s`, calculate its **reverse degree**.
+
+The **reverse degree** is calculated as follows:
+
+1. For each character, multiply its position in the _reversed_ alphabet (`'a'` = 26, `'b'` = 25, ..., `'z'` = 1) with its position in the string **(1-indexed)**.
+2. Sum these products for all characters in the string.
+
+Return the **reverse degree** of `s`.
+
+**Example 1:**
+
+**Input:** s = "abc"
+
+**Output:** 148
+
+**Explanation:**
+
+| Letter | Index in Reversed Alphabet | Index in String | Product |
+|---------|----------------------------|----------------|---------|
+| `'a'` | 26 | 1 | 26 |
+| `'b'` | 25 | 2 | 50 |
+| `'c'` | 24 | 3 | 72 |
+
+The reversed degree is `26 + 50 + 72 = 148`.
+
+**Example 2:**
+
+**Input:** s = "zaza"
+
+**Output:** 160
+
+**Explanation:**
+
+| Letter | Index in Reversed Alphabet | Index in String | Product |
+|---------|----------------------------|----------------|---------|
+| `'z'` | 1 | 1 | 1 |
+| `'a'` | 26 | 2 | 52 |
+| `'z'` | 1 | 3 | 3 |
+| `'a'` | 26 | 4 | 104 |
+
+The reverse degree is `1 + 52 + 3 + 104 = 160`.
+
+**Constraints:**
+
+* `1 <= s.length <= 1000`
+* `s` contains only lowercase English letters.
\ No newline at end of file
diff --git a/src/main/java/g3401_3500/s3499_maximize_active_section_with_trade_i/Solution.java b/src/main/java/g3401_3500/s3499_maximize_active_section_with_trade_i/Solution.java
new file mode 100644
index 000000000..d1ba88bc6
--- /dev/null
+++ b/src/main/java/g3401_3500/s3499_maximize_active_section_with_trade_i/Solution.java
@@ -0,0 +1,29 @@
+package g3401_3500.s3499_maximize_active_section_with_trade_i;
+
+// #Medium #String #Enumeration #2025_04_01_Time_54_ms_(97.98%)_Space_45.89_MB_(76.19%)
+
+public class Solution {
+ public int maxActiveSectionsAfterTrade(String s) {
+ int oneCount = 0;
+ int convertedOne = 0;
+ int curZeroCount = 0;
+ int lastZeroCount = 0;
+ for (int i = 0; i < s.length(); ++i) {
+ if (s.charAt(i) == '0') {
+ curZeroCount++;
+ } else {
+ if (curZeroCount != 0) {
+ lastZeroCount = curZeroCount;
+ }
+ curZeroCount = 0;
+ oneCount++;
+ }
+ convertedOne = Math.max(convertedOne, curZeroCount + lastZeroCount);
+ }
+ // corner case
+ if (convertedOne == curZeroCount || convertedOne == lastZeroCount) {
+ return oneCount;
+ }
+ return oneCount + convertedOne;
+ }
+}
diff --git a/src/main/java/g3401_3500/s3499_maximize_active_section_with_trade_i/readme.md b/src/main/java/g3401_3500/s3499_maximize_active_section_with_trade_i/readme.md
new file mode 100644
index 000000000..2d6c49c5a
--- /dev/null
+++ b/src/main/java/g3401_3500/s3499_maximize_active_section_with_trade_i/readme.md
@@ -0,0 +1,68 @@
+3499\. Maximize Active Section with Trade I
+
+Medium
+
+You are given a binary string `s` of length `n`, where:
+
+* `'1'` represents an **active** section.
+* `'0'` represents an **inactive** section.
+
+You can perform **at most one trade** to maximize the number of active sections in `s`. In a trade, you:
+
+* Convert a contiguous block of `'1'`s that is surrounded by `'0'`s to all `'0'`s.
+* Afterward, convert a contiguous block of `'0'`s that is surrounded by `'1'`s to all `'1'`s.
+
+Return the **maximum** number of active sections in `s` after making the optimal trade.
+
+**Note:** Treat `s` as if it is **augmented** with a `'1'` at both ends, forming `t = '1' + s + '1'`. The augmented `'1'`s **do not** contribute to the final count.
+
+**Example 1:**
+
+**Input:** s = "01"
+
+**Output:** 1
+
+**Explanation:**
+
+Because there is no block of `'1'`s surrounded by `'0'`s, no valid trade is possible. The maximum number of active sections is 1.
+
+**Example 2:**
+
+**Input:** s = "0100"
+
+**Output:** 4
+
+**Explanation:**
+
+* String `"0100"` → Augmented to `"101001"`.
+* Choose `"0100"`, convert "10**1**001"
→ "1**0000**1"
→ "1**1111**1"
.
+* The final string without augmentation is `"1111"`. The maximum number of active sections is 4.
+
+**Example 3:**
+
+**Input:** s = "1000100"
+
+**Output:** 7
+
+**Explanation:**
+
+* String `"1000100"` → Augmented to `"110001001"`.
+* Choose `"000100"`, convert "11000**1**001"
→ "11**000000**1"
→ "11**111111**1"
.
+* The final string without augmentation is `"1111111"`. The maximum number of active sections is 7.
+
+**Example 4:**
+
+**Input:** s = "01010"
+
+**Output:** 4
+
+**Explanation:**
+
+* String `"01010"` → Augmented to `"1010101"`.
+* Choose `"010"`, convert "10**1**0101"
→ "1**000**101"
→ "1**111**101"
.
+* The final string without augmentation is `"11110"`. The maximum number of active sections is 4.
+
+**Constraints:**
+
+* 1 <= n == s.length <= 105
+* `s[i]` is either `'0'` or `'1'`
\ No newline at end of file
diff --git a/src/main/java/g3401_3500/s3500_minimum_cost_to_divide_array_into_subarrays/Solution.java b/src/main/java/g3401_3500/s3500_minimum_cost_to_divide_array_into_subarrays/Solution.java
new file mode 100644
index 000000000..b52cf7870
--- /dev/null
+++ b/src/main/java/g3401_3500/s3500_minimum_cost_to_divide_array_into_subarrays/Solution.java
@@ -0,0 +1,31 @@
+package g3401_3500.s3500_minimum_cost_to_divide_array_into_subarrays;
+
+// #Hard #Array #Dynamic_Programming #Prefix_Sum
+// #2025_04_01_Time_26_ms_(93.46%)_Space_44.97_MB_(94.77%)
+
+@SuppressWarnings("java:S107")
+public class Solution {
+ public long minimumCost(int[] nums, int[] cost, int k) {
+ int n = nums.length;
+ long kLong = k;
+ long[] preNums = new long[n + 1];
+ long[] preCost = new long[n + 1];
+ for (int i = 0; i < n; i++) {
+ preNums[i + 1] = preNums[i] + nums[i];
+ preCost[i + 1] = preCost[i] + cost[i];
+ }
+ long[] dp = new long[n + 1];
+ for (int i = 0; i <= n; i++) {
+ dp[i] = Long.MAX_VALUE / 2;
+ }
+ dp[0] = 0L;
+ for (int r = 1; r <= n; r++) {
+ for (int l = 0; l < r; l++) {
+ long sumNums = preNums[r] * (preCost[r] - preCost[l]);
+ long sumCost = kLong * (preCost[n] - preCost[l]);
+ dp[r] = Math.min(dp[r], dp[l] + sumNums + sumCost);
+ }
+ }
+ return dp[n];
+ }
+}
diff --git a/src/main/java/g3401_3500/s3500_minimum_cost_to_divide_array_into_subarrays/readme.md b/src/main/java/g3401_3500/s3500_minimum_cost_to_divide_array_into_subarrays/readme.md
new file mode 100644
index 000000000..0c94b088f
--- /dev/null
+++ b/src/main/java/g3401_3500/s3500_minimum_cost_to_divide_array_into_subarrays/readme.md
@@ -0,0 +1,47 @@
+3500\. Minimum Cost to Divide Array Into Subarrays
+
+Hard
+
+You are given two integer arrays, `nums` and `cost`, of the same size, and an integer `k`.
+
+You can divide `nums` into **non-empty subarrays**. The cost of the ith
subarray consisting of elements `nums[l..r]` is:
+
+* `(nums[0] + nums[1] + ... + nums[r] + k * i) * (cost[l] + cost[l + 1] + ... + cost[r])`.
+
+**Note** that `i` represents the order of the subarray: 1 for the first subarray, 2 for the second, and so on.
+
+Return the **minimum** total cost possible from any valid division.
+
+**Example 1:**
+
+**Input:** nums = [3,1,4], cost = [4,6,6], k = 1
+
+**Output:** 110
+
+**Explanation:**
+
+The minimum total cost possible can be achieved by dividing `nums` into subarrays `[3, 1]` and `[4]`.
+
+* The cost of the first subarray `[3,1]` is `(3 + 1 + 1 * 1) * (4 + 6) = 50`.
+* The cost of the second subarray `[4]` is `(3 + 1 + 4 + 1 * 2) * 6 = 60`.
+
+**Example 2:**
+
+**Input:** nums = [4,8,5,1,14,2,2,12,1], cost = [7,2,8,4,2,2,1,1,2], k = 7
+
+**Output:** 985
+
+**Explanation:**
+
+The minimum total cost possible can be achieved by dividing `nums` into subarrays `[4, 8, 5, 1]`, `[14, 2, 2]`, and `[12, 1]`.
+
+* The cost of the first subarray `[4, 8, 5, 1]` is `(4 + 8 + 5 + 1 + 7 * 1) * (7 + 2 + 8 + 4) = 525`.
+* The cost of the second subarray `[14, 2, 2]` is `(4 + 8 + 5 + 1 + 14 + 2 + 2 + 7 * 2) * (2 + 2 + 1) = 250`.
+* The cost of the third subarray `[12, 1]` is `(4 + 8 + 5 + 1 + 14 + 2 + 2 + 12 + 1 + 7 * 3) * (1 + 2) = 210`.
+
+**Constraints:**
+
+* `1 <= nums.length <= 1000`
+* `cost.length == nums.length`
+* `1 <= nums[i], cost[i] <= 1000`
+* `1 <= k <= 1000`
\ No newline at end of file
diff --git a/src/main/java/g3501_3600/s3501_maximize_active_section_with_trade_ii/Solution.java b/src/main/java/g3501_3600/s3501_maximize_active_section_with_trade_ii/Solution.java
new file mode 100644
index 000000000..8823124cd
--- /dev/null
+++ b/src/main/java/g3501_3600/s3501_maximize_active_section_with_trade_ii/Solution.java
@@ -0,0 +1,126 @@
+package g3501_3600.s3501_maximize_active_section_with_trade_ii;
+
+// #Hard #Array #String #Binary_Search #Segment_Tree
+// #2025_04_01_Time_256_ms_(63.33%)_Space_106.80_MB_(56.67%)
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class Solution {
+ private static final int INF = (int) 1e9;
+ private static final int NEG_INF = -INF;
+
+ public List maxActiveSectionsAfterTrade(String s, int[][] queries) {
+ int n = s.length();
+ int activeCount = 0;
+ for (char ch : s.toCharArray()) {
+ if (ch == '1') {
+ activeCount++;
+ }
+ }
+ List segments = new ArrayList<>();
+ int start = 0;
+ for (int i = 0; i < n; i++) {
+ if (i == n - 1 || s.charAt(i) != s.charAt(i + 1)) {
+ segments.add(new int[] {start, i - start + 1});
+ start = i + 1;
+ }
+ }
+ int segmentCount = segments.size();
+ int maxPower = 20;
+ int[][] rmq = new int[maxPower][segmentCount];
+ for (int i = 0; i < maxPower; i++) {
+ Arrays.fill(rmq[i], NEG_INF);
+ }
+ for (int i = 0; i < segmentCount; i++) {
+ if (s.charAt(segments.get(i)[0]) == '0' && i + 2 < segmentCount) {
+ rmq[0][i] = segments.get(i)[1] + segments.get(i + 2)[1];
+ }
+ }
+ for (int power = 1, rangeLen = 2; power < maxPower; power++, rangeLen *= 2) {
+ for (int i = 0, j = rangeLen - 1; j < segmentCount; i++, j++) {
+ rmq[power][i] = Math.max(rmq[power - 1][i], rmq[power - 1][i + rangeLen / 2]);
+ }
+ }
+ List result = new ArrayList<>();
+ for (int[] query : queries) {
+ int left = query[0];
+ int right = query[1];
+ int leftIndex = binarySearch(segments, left) - 1;
+ int rightIndex = binarySearch(segments, right) - 1;
+ if (rightIndex - leftIndex + 1 <= 2) {
+ result.add(activeCount);
+ continue;
+ }
+ int bestIncrease = Math.max(getMaxInRange(rmq, leftIndex + 1, rightIndex - 3), 0);
+ bestIncrease =
+ Math.max(
+ bestIncrease,
+ calculateNewSections(
+ s, segments, left, right, leftIndex, rightIndex, leftIndex));
+ bestIncrease =
+ Math.max(
+ bestIncrease,
+ calculateNewSections(
+ s,
+ segments,
+ left,
+ right,
+ leftIndex,
+ rightIndex,
+ rightIndex - 2));
+ result.add(activeCount + bestIncrease);
+ }
+ return result;
+ }
+
+ private int binarySearch(List segments, int key) {
+ int lo = 0;
+ int hi = segments.size();
+ while (lo < hi) {
+ int mid = lo + (hi - lo) / 2;
+ if (segments.get(mid)[0] > key) {
+ hi = mid;
+ } else {
+ lo = mid + 1;
+ }
+ }
+ return lo;
+ }
+
+ private int getMaxInRange(int[][] rmq, int left, int right) {
+ if (left > right) {
+ return NEG_INF;
+ }
+ int power = 31 - Integer.numberOfLeadingZeros(right - left + 1);
+ return Math.max(rmq[power][left], rmq[power][right - (1 << power) + 1]);
+ }
+
+ private int getSegmentSize(
+ List segments, int left, int right, int leftIndex, int rightIndex, int i) {
+ if (i == leftIndex) {
+ return segments.get(leftIndex)[1] - (left - segments.get(leftIndex)[0]);
+ }
+ if (i == rightIndex) {
+ return right - segments.get(rightIndex)[0] + 1;
+ }
+ return segments.get(i)[1];
+ }
+
+ private int calculateNewSections(
+ String s,
+ List segments,
+ int left,
+ int right,
+ int leftIndex,
+ int rightIndex,
+ int i) {
+ if (i < 0 || i + 2 >= segments.size() || s.charAt(segments.get(i)[0]) == '1') {
+ return NEG_INF;
+ }
+ int size1 = getSegmentSize(segments, left, right, leftIndex, rightIndex, i);
+ int size2 = getSegmentSize(segments, left, right, leftIndex, rightIndex, i + 2);
+ return size1 + size2;
+ }
+}
diff --git a/src/main/java/g3501_3600/s3501_maximize_active_section_with_trade_ii/readme.md b/src/main/java/g3501_3600/s3501_maximize_active_section_with_trade_ii/readme.md
new file mode 100644
index 000000000..740d75a33
--- /dev/null
+++ b/src/main/java/g3501_3600/s3501_maximize_active_section_with_trade_ii/readme.md
@@ -0,0 +1,105 @@
+3501\. Maximize Active Section with Trade II
+
+Hard
+
+You are given a binary string `s` of length `n`, where:
+
+* `'1'` represents an **active** section.
+* `'0'` represents an **inactive** section.
+
+You can perform **at most one trade** to maximize the number of active sections in `s`. In a trade, you:
+
+* Convert a contiguous block of `'1'`s that is surrounded by `'0'`s to all `'0'`s.
+* Afterward, convert a contiguous block of `'0'`s that is surrounded by `'1'`s to all `'1'`s.
+
+Additionally, you are given a **2D array** `queries`, where queries[i] = [li, ri]
represents a **substring** s[li...ri]
.
+
+For each query, determine the **maximum** possible number of active sections in `s` after making the optimal trade on the substring s[li...ri]
.
+
+Return an array `answer`, where `answer[i]` is the result for `queries[i]`.
+
+**Note**
+
+* For each query, treat s[li...ri]
as if it is **augmented** with a `'1'` at both ends, forming t = '1' + s[li...ri] + '1'
. The augmented `'1'`s **do not** contribute to the final count.
+* The queries are independent of each other.
+
+**Example 1:**
+
+**Input:** s = "01", queries = [[0,1]]
+
+**Output:** [1]
+
+**Explanation:**
+
+Because there is no block of `'1'`s surrounded by `'0'`s, no valid trade is possible. The maximum number of active sections is 1.
+
+**Example 2:**
+
+**Input:** s = "0100", queries = [[0,3],[0,2],[1,3],[2,3]]
+
+**Output:** [4,3,1,1]
+
+**Explanation:**
+
+* Query `[0, 3]` → Substring `"0100"` → Augmented to `"101001"`
+ Choose `"0100"`, convert `"0100"` → `"0000"` → `"1111"`.
+ The final string without augmentation is `"1111"`. The maximum number of active sections is 4.
+
+* Query `[0, 2]` → Substring `"010"` → Augmented to `"10101"`
+ Choose `"010"`, convert `"010"` → `"000"` → `"111"`.
+ The final string without augmentation is `"1110"`. The maximum number of active sections is 3.
+
+* Query `[1, 3]` → Substring `"100"` → Augmented to `"11001"`
+ Because there is no block of `'1'`s surrounded by `'0'`s, no valid trade is possible. The maximum number of active sections is 1.
+
+* Query `[2, 3]` → Substring `"00"` → Augmented to `"1001"`
+ Because there is no block of `'1'`s surrounded by `'0'`s, no valid trade is possible. The maximum number of active sections is 1.
+
+
+**Example 3:**
+
+**Input:** s = "1000100", queries = [[1,5],[0,6],[0,4]]
+
+**Output:** [6,7,2]
+
+**Explanation:**
+
+* Query `[1, 5]` → Substring `"00010"` → Augmented to `"1000101"`
+ Choose `"00010"`, convert `"00010"` → `"00000"` → `"11111"`.
+ The final string without augmentation is `"1111110"`. The maximum number of active sections is 6.
+
+* Query `[0, 6]` → Substring `"1000100"` → Augmented to `"110001001"`
+ Choose `"000100"`, convert `"000100"` → `"000000"` → `"111111"`.
+ The final string without augmentation is `"1111111"`. The maximum number of active sections is 7.
+
+* Query `[0, 4]` → Substring `"10001"` → Augmented to `"1100011"`
+ Because there is no block of `'1'`s surrounded by `'0'`s, no valid trade is possible. The maximum number of active sections is 2.
+
+
+**Example 4:**
+
+**Input:** s = "01010", queries = [[0,3],[1,4],[1,3]]
+
+**Output:** [4,4,2]
+
+**Explanation:**
+
+* Query `[0, 3]` → Substring `"0101"` → Augmented to `"101011"`
+ Choose `"010"`, convert `"010"` → `"000"` → `"111"`.
+ The final string without augmentation is `"11110"`. The maximum number of active sections is 4.
+
+* Query `[1, 4]` → Substring `"1010"` → Augmented to `"110101"`
+ Choose `"010"`, convert `"010"` → `"000"` → `"111"`.
+ The final string without augmentation is `"01111"`. The maximum number of active sections is 4.
+
+* Query `[1, 3]` → Substring `"101"` → Augmented to `"11011"`
+ Because there is no block of `'1'`s surrounded by `'0'`s, no valid trade is possible. The maximum number of active sections is 2.
+
+
+**Constraints:**
+
+* 1 <= n == s.length <= 105
+* 1 <= queries.length <= 105
+* `s[i]` is either `'0'` or `'1'`.
+* queries[i] = [li, ri]
+* 0 <= li <= ri < n
\ No newline at end of file
diff --git a/src/main/java/g3501_3600/s3502_minimum_cost_to_reach_every_position/Solution.java b/src/main/java/g3501_3600/s3502_minimum_cost_to_reach_every_position/Solution.java
new file mode 100644
index 000000000..e408695e5
--- /dev/null
+++ b/src/main/java/g3501_3600/s3502_minimum_cost_to_reach_every_position/Solution.java
@@ -0,0 +1,16 @@
+package g3501_3600.s3502_minimum_cost_to_reach_every_position;
+
+// #Easy #Array #2025_04_01_Time_1_ms_(97.59%)_Space_44.92_MB_(69.12%)
+
+public class Solution {
+ public int[] minCosts(int[] cost) {
+ int min = cost[0];
+ int[] ans = new int[cost.length];
+ ans[0] = min;
+ for (int i = 1; i < cost.length; i++) {
+ min = Math.min(min, cost[i]);
+ ans[i] = min;
+ }
+ return ans;
+ }
+}
diff --git a/src/main/java/g3501_3600/s3502_minimum_cost_to_reach_every_position/readme.md b/src/main/java/g3501_3600/s3502_minimum_cost_to_reach_every_position/readme.md
new file mode 100644
index 000000000..f3e580876
--- /dev/null
+++ b/src/main/java/g3501_3600/s3502_minimum_cost_to_reach_every_position/readme.md
@@ -0,0 +1,46 @@
+3502\. Minimum Cost to Reach Every Position
+
+Easy
+
+You are given an integer array `cost` of size `n`. You are currently at position `n` (at the end of the line) in a line of `n + 1` people (numbered from 0 to `n`).
+
+You wish to move forward in the line, but each person in front of you charges a specific amount to **swap** places. The cost to swap with person `i` is given by `cost[i]`.
+
+You are allowed to swap places with people as follows:
+
+* If they are in front of you, you **must** pay them `cost[i]` to swap with them.
+* If they are behind you, they can swap with you for free.
+
+Return an array `answer` of size `n`, where `answer[i]` is the **minimum** total cost to reach each position `i` in the line.
+
+**Example 1:**
+
+**Input:** cost = [5,3,4,1,3,2]
+
+**Output:** [5,3,3,1,1,1]
+
+**Explanation:**
+
+We can get to each position in the following way:
+
+* `i = 0`. We can swap with person 0 for a cost of 5.
+* `i = 1`. We can swap with person 1 for a cost of 3.
+* `i = 2`. We can swap with person 1 for a cost of 3, then swap with person 2 for free.
+* `i = 3`. We can swap with person 3 for a cost of 1.
+* `i = 4`. We can swap with person 3 for a cost of 1, then swap with person 4 for free.
+* `i = 5`. We can swap with person 3 for a cost of 1, then swap with person 5 for free.
+
+**Example 2:**
+
+**Input:** cost = [1,2,4,6,7]
+
+**Output:** [1,1,1,1,1]
+
+**Explanation:**
+
+We can swap with person 0 for a cost of 1, then we will be able to reach any position `i` for free.
+
+**Constraints:**
+
+* `1 <= n == cost.length <= 100`
+* `1 <= cost[i] <= 100`
\ No newline at end of file
diff --git a/src/main/java/g3501_3600/s3503_longest_palindrome_after_substring_concatenation_i/Solution.java b/src/main/java/g3501_3600/s3503_longest_palindrome_after_substring_concatenation_i/Solution.java
new file mode 100644
index 000000000..ea31e6d0d
--- /dev/null
+++ b/src/main/java/g3501_3600/s3503_longest_palindrome_after_substring_concatenation_i/Solution.java
@@ -0,0 +1,76 @@
+package g3501_3600.s3503_longest_palindrome_after_substring_concatenation_i;
+
+// #Medium #String #Dynamic_Programming #Two_Pointers #Enumeration
+// #2025_04_01_Time_30_ms_(97.15%)_Space_42.23_MB_(99.79%)
+
+public class Solution {
+ public int longestPalindrome(String s, String t) {
+ int maxLen = 0;
+ maxLen = Math.max(maxLen, longestPalindromicSubstring(s));
+ maxLen = Math.max(maxLen, longestPalindromicSubstring(t));
+ int sLen = s.length();
+ int tLen = t.length();
+ for (int i = 0; i < sLen; i++) {
+ for (int j = i; j < sLen; j++) {
+ int m = j - i + 1;
+ for (int k = 0; k < tLen; k++) {
+ for (int l = k; l < tLen; l++) {
+ int n = l - k + 1;
+ int totalLength = m + n;
+ if (totalLength <= maxLen) {
+ continue;
+ }
+ boolean isPalindrome = true;
+ for (int p = 0; p < totalLength / 2; p++) {
+ int q = totalLength - 1 - p;
+ char c1;
+ char c2;
+ if (p < m) {
+ c1 = s.charAt(i + p);
+ } else {
+ c1 = t.charAt(k + (p - m));
+ }
+ if (q < m) {
+ c2 = s.charAt(i + q);
+ } else {
+ c2 = t.charAt(k + (q - m));
+ }
+ if (c1 != c2) {
+ isPalindrome = false;
+ break;
+ }
+ }
+ if (isPalindrome) {
+ maxLen = totalLength;
+ }
+ }
+ }
+ }
+ }
+ return maxLen;
+ }
+
+ private int longestPalindromicSubstring(String str) {
+ int max = 0;
+ int len = str.length();
+ for (int i = 0; i < len; i++) {
+ for (int j = i; j < len; j++) {
+ boolean isPalin = true;
+ int left = i;
+ int right = j;
+ while (left < right) {
+ if (str.charAt(left) != str.charAt(right)) {
+ isPalin = false;
+ break;
+ }
+ left++;
+ right--;
+ }
+ if (isPalin) {
+ max = Math.max(max, j - i + 1);
+ }
+ }
+ }
+ return max;
+ }
+}
diff --git a/src/main/java/g3501_3600/s3503_longest_palindrome_after_substring_concatenation_i/readme.md b/src/main/java/g3501_3600/s3503_longest_palindrome_after_substring_concatenation_i/readme.md
new file mode 100644
index 000000000..e340325e0
--- /dev/null
+++ b/src/main/java/g3501_3600/s3503_longest_palindrome_after_substring_concatenation_i/readme.md
@@ -0,0 +1,54 @@
+3503\. Longest Palindrome After Substring Concatenation I
+
+Medium
+
+You are given two strings, `s` and `t`.
+
+You can create a new string by selecting a **substring** from `s` (possibly empty) and a substring from `t` (possibly empty), then concatenating them **in order**.
+
+Return the length of the **longest** palindrome that can be formed this way.
+
+**Example 1:**
+
+**Input:** s = "a", t = "a"
+
+**Output:** 2
+
+**Explanation:**
+
+Concatenating `"a"` from `s` and `"a"` from `t` results in `"aa"`, which is a palindrome of length 2.
+
+**Example 2:**
+
+**Input:** s = "abc", t = "def"
+
+**Output:** 1
+
+**Explanation:**
+
+Since all characters are different, the longest palindrome is any single character, so the answer is 1.
+
+**Example 3:**
+
+**Input:** s = "b", t = "aaaa"
+
+**Output:** 4
+
+**Explanation:**
+
+Selecting "`aaaa`" from `t` is the longest palindrome, so the answer is 4.
+
+**Example 4:**
+
+**Input:** s = "abcde", t = "ecdba"
+
+**Output:** 5
+
+**Explanation:**
+
+Concatenating `"abc"` from `s` and `"ba"` from `t` results in `"abcba"`, which is a palindrome of length 5.
+
+**Constraints:**
+
+* `1 <= s.length, t.length <= 30`
+* `s` and `t` consist of lowercase English letters.
\ No newline at end of file
diff --git a/src/main/java/g3501_3600/s3504_longest_palindrome_after_substring_concatenation_ii/Solution.java b/src/main/java/g3501_3600/s3504_longest_palindrome_after_substring_concatenation_ii/Solution.java
new file mode 100644
index 000000000..e74cd9961
--- /dev/null
+++ b/src/main/java/g3501_3600/s3504_longest_palindrome_after_substring_concatenation_ii/Solution.java
@@ -0,0 +1,83 @@
+package g3501_3600.s3504_longest_palindrome_after_substring_concatenation_ii;
+
+// #Hard #String #Dynamic_Programming #Two_Pointers
+// #2025_04_01_Time_25_ms_(99.50%)_Space_52.97_MB_(90.50%)
+
+public class Solution {
+ private int[] sPa;
+ private int[] tPa;
+ private char[] ss;
+ private char[] tt;
+
+ public int longestPalindrome(String s, String t) {
+ final int sLen = s.length();
+ final int tLen = t.length();
+ ss = s.toCharArray();
+ tt = t.toCharArray();
+ int[][] palindrome = new int[sLen][tLen + 1];
+ sPa = new int[sLen];
+ tPa = new int[tLen];
+ int maxLen = 1;
+ for (int j = 0; j < tLen; j++) {
+ if (ss[0] == tt[j]) {
+ palindrome[0][j] = 2;
+ sPa[0] = 2;
+ tPa[j] = 2;
+ maxLen = 2;
+ }
+ }
+ for (int i = 1; i < sLen; i++) {
+ for (int j = 0; j < tLen; j++) {
+ if (ss[i] == tt[j]) {
+ palindrome[i][j] = 2 + palindrome[i - 1][j + 1];
+ sPa[i] = Math.max(sPa[i], palindrome[i][j]);
+ tPa[j] = Math.max(tPa[j], palindrome[i][j]);
+ maxLen = Math.max(maxLen, palindrome[i][j]);
+ }
+ }
+ }
+ for (int i = 0; i < sLen - 1; i++) {
+ int len = maxS(i, i + 1);
+ maxLen = Math.max(maxLen, len);
+ }
+ for (int i = 1; i < sLen; i++) {
+ int len = maxS(i - 1, i + 1) + 1;
+ maxLen = Math.max(maxLen, len);
+ }
+ for (int j = 0; j < tLen - 1; j++) {
+ int len = maxT(j, j + 1);
+ maxLen = Math.max(maxLen, len);
+ }
+ for (int j = 0; j < tLen - 1; j++) {
+ int len = maxT(j - 1, j + 1) + 1;
+ maxLen = Math.max(maxLen, len);
+ }
+ return maxLen;
+ }
+
+ private int maxS(int left, int right) {
+ int len = 0;
+ while (left >= 0 && right < ss.length && ss[left] == ss[right]) {
+ len += 2;
+ left--;
+ right++;
+ }
+ if (left >= 0) {
+ len += sPa[left];
+ }
+ return len;
+ }
+
+ private int maxT(int left, int right) {
+ int len = 0;
+ while (left >= 0 && right < tt.length && tt[left] == tt[right]) {
+ len += 2;
+ left--;
+ right++;
+ }
+ if (right < tt.length) {
+ len += tPa[right];
+ }
+ return len;
+ }
+}
diff --git a/src/main/java/g3501_3600/s3504_longest_palindrome_after_substring_concatenation_ii/readme.md b/src/main/java/g3501_3600/s3504_longest_palindrome_after_substring_concatenation_ii/readme.md
new file mode 100644
index 000000000..8760ac849
--- /dev/null
+++ b/src/main/java/g3501_3600/s3504_longest_palindrome_after_substring_concatenation_ii/readme.md
@@ -0,0 +1,54 @@
+3504\. Longest Palindrome After Substring Concatenation II
+
+Hard
+
+You are given two strings, `s` and `t`.
+
+You can create a new string by selecting a **substring** from `s` (possibly empty) and a substring from `t` (possibly empty), then concatenating them **in order**.
+
+Return the length of the **longest** palindrome that can be formed this way.
+
+**Example 1:**
+
+**Input:** s = "a", t = "a"
+
+**Output:** 2
+
+**Explanation:**
+
+Concatenating `"a"` from `s` and `"a"` from `t` results in `"aa"`, which is a palindrome of length 2.
+
+**Example 2:**
+
+**Input:** s = "abc", t = "def"
+
+**Output:** 1
+
+**Explanation:**
+
+Since all characters are different, the longest palindrome is any single character, so the answer is 1.
+
+**Example 3:**
+
+**Input:** s = "b", t = "aaaa"
+
+**Output:** 4
+
+**Explanation:**
+
+Selecting "`aaaa`" from `t` is the longest palindrome, so the answer is 4.
+
+**Example 4:**
+
+**Input:** s = "abcde", t = "ecdba"
+
+**Output:** 5
+
+**Explanation:**
+
+Concatenating `"abc"` from `s` and `"ba"` from `t` results in `"abcba"`, which is a palindrome of length 5.
+
+**Constraints:**
+
+* `1 <= s.length, t.length <= 1000`
+* `s` and `t` consist of lowercase English letters.
\ No newline at end of file
diff --git a/src/main/java/g3501_3600/s3505_minimum_operations_to_make_elements_within_k_subarrays_equal/Solution.java b/src/main/java/g3501_3600/s3505_minimum_operations_to_make_elements_within_k_subarrays_equal/Solution.java
new file mode 100644
index 000000000..e72a3c852
--- /dev/null
+++ b/src/main/java/g3501_3600/s3505_minimum_operations_to_make_elements_within_k_subarrays_equal/Solution.java
@@ -0,0 +1,137 @@
+package g3501_3600.s3505_minimum_operations_to_make_elements_within_k_subarrays_equal;
+
+// #Hard #Array #Hash_Table #Dynamic_Programming #Math #Heap_Priority_Queue #Sliding_Window
+// #2025_04_01_Time_547_ms_(77.95%)_Space_82.16_MB_(16.92%)
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.PriorityQueue;
+
+public class Solution {
+ private static class SlidingMedian {
+ // max-heap for smaller half
+ PriorityQueue leftHeap;
+ // min-heap for larger half
+ PriorityQueue rightHeap;
+ Map delayedRemovals;
+ long sumLeft;
+ long sumRight;
+ int sizeLeft;
+ int sizeRight;
+
+ public SlidingMedian() {
+ leftHeap = new PriorityQueue<>(Collections.reverseOrder());
+ rightHeap = new PriorityQueue<>();
+ delayedRemovals = new HashMap<>();
+ sumLeft = sumRight = 0;
+ sizeLeft = sizeRight = 0;
+ }
+
+ public void add(int num) {
+ if (leftHeap.isEmpty() || num <= leftHeap.peek()) {
+ leftHeap.offer(num);
+ sumLeft += num;
+ sizeLeft++;
+ } else {
+ rightHeap.offer(num);
+ sumRight += num;
+ sizeRight++;
+ }
+ balanceHeaps();
+ }
+
+ public void remove(int num) {
+ delayedRemovals.put(num, delayedRemovals.getOrDefault(num, 0) + 1);
+ if (!leftHeap.isEmpty() && num <= leftHeap.peek()) {
+ sumLeft -= num;
+ sizeLeft--;
+ } else {
+ sumRight -= num;
+ sizeRight--;
+ }
+ balanceHeaps();
+ pruneHeap(leftHeap);
+ pruneHeap(rightHeap);
+ }
+
+ private void balanceHeaps() {
+ if (sizeLeft > sizeRight + 1) {
+ int num = leftHeap.poll();
+ sumLeft -= num;
+ sizeLeft--;
+ rightHeap.offer(num);
+ sumRight += num;
+ sizeRight++;
+ } else if (sizeRight > sizeLeft) {
+ int num = rightHeap.poll();
+ sumRight -= num;
+ sizeRight--;
+ leftHeap.offer(num);
+ sumLeft += num;
+ sizeLeft++;
+ }
+ }
+
+ private void pruneHeap(PriorityQueue heap) {
+ while (!heap.isEmpty() && delayedRemovals.containsKey(heap.peek())) {
+ int num = heap.peek();
+ if (delayedRemovals.get(num) > 0) {
+ heap.poll();
+ delayedRemovals.put(num, delayedRemovals.get(num) - 1);
+ if (delayedRemovals.get(num) == 0) {
+ delayedRemovals.remove(num);
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ public int getMedian() {
+ return leftHeap.peek();
+ }
+
+ public long getCost() {
+ int median = getMedian();
+ return (long) median * sizeLeft - sumLeft + sumRight - (long) median * sizeRight;
+ }
+ }
+
+ public long minOperations(int[] nums, int x, int k) {
+ int n = nums.length;
+ int windowCount = n - x + 1;
+ long[] costs = new long[windowCount];
+ SlidingMedian sm = new SlidingMedian();
+ // Compute costs for all windows
+ for (int i = 0; i < x; i++) {
+ sm.add(nums[i]);
+ }
+ costs[0] = sm.getCost();
+ for (int i = 1; i < windowCount; i++) {
+ sm.remove(nums[i - 1]);
+ sm.add(nums[i + x - 1]);
+ costs[i] = sm.getCost();
+ }
+ // Dynamic programming table
+ long[][] dp = new long[windowCount][k + 1];
+ for (long[] row : dp) {
+ Arrays.fill(row, Long.MAX_VALUE / 2);
+ }
+ dp[0][0] = 0;
+ for (int i = 0; i < windowCount; i++) {
+ for (int j = 0; j <= k; j++) {
+ if (i > 0) {
+ dp[i][j] = Math.min(dp[i][j], dp[i - 1][j]);
+ }
+ if (j > 0 && i >= x) {
+ dp[i][j] = Math.min(dp[i][j], dp[i - x][j - 1] + costs[i]);
+ } else if (j == 1) {
+ dp[i][j] = Math.min(dp[i][j], costs[i]);
+ }
+ }
+ }
+ return dp[windowCount - 1][k];
+ }
+}
diff --git a/src/main/java/g3501_3600/s3505_minimum_operations_to_make_elements_within_k_subarrays_equal/readme.md b/src/main/java/g3501_3600/s3505_minimum_operations_to_make_elements_within_k_subarrays_equal/readme.md
new file mode 100644
index 000000000..439402d64
--- /dev/null
+++ b/src/main/java/g3501_3600/s3505_minimum_operations_to_make_elements_within_k_subarrays_equal/readme.md
@@ -0,0 +1,40 @@
+3505\. Minimum Operations to Make Elements Within K Subarrays Equal
+
+Hard
+
+You are given an integer array `nums` and two integers, `x` and `k`. You can perform the following operation any number of times (**including zero**):
+
+* Increase or decrease any element of `nums` by 1.
+
+Return the **minimum** number of operations needed to have **at least** `k` _non-overlapping **non-empty subarrays**_ of size **exactly** `x` in `nums`, where all elements within each subarray are equal.
+
+**Example 1:**
+
+**Input:** nums = [5,-2,1,3,7,3,6,4,-1], x = 3, k = 2
+
+**Output:** 8
+
+**Explanation:**
+
+* Use 3 operations to add 3 to `nums[1]` and use 2 operations to subtract 2 from `nums[3]`. The resulting array is `[5, 1, 1, 1, 7, 3, 6, 4, -1]`.
+* Use 1 operation to add 1 to `nums[5]` and use 2 operations to subtract 2 from `nums[6]`. The resulting array is `[5, 1, 1, 1, 7, 4, 4, 4, -1]`.
+* Now, all elements within each subarray `[1, 1, 1]` (from indices 1 to 3) and `[4, 4, 4]` (from indices 5 to 7) are equal. Since 8 total operations were used, 8 is the output.
+
+**Example 2:**
+
+**Input:** nums = [9,-2,-2,-2,1,5], x = 2, k = 2
+
+**Output:** 3
+
+**Explanation:**
+
+* Use 3 operations to subtract 3 from `nums[4]`. The resulting array is `[9, -2, -2, -2, -2, 5]`.
+* Now, all elements within each subarray `[-2, -2]` (from indices 1 to 2) and `[-2, -2]` (from indices 3 to 4) are equal. Since 3 operations were used, 3 is the output.
+
+**Constraints:**
+
+* 2 <= nums.length <= 105
+* -106 <= nums[i] <= 106
+* `2 <= x <= nums.length`
+* `1 <= k <= 15`
+* `2 <= k * x <= nums.length`
\ No newline at end of file
diff --git a/src/test/java/g3401_3500/s3498_reverse_degree_of_a_string/SolutionTest.java b/src/test/java/g3401_3500/s3498_reverse_degree_of_a_string/SolutionTest.java
new file mode 100644
index 000000000..82a81094a
--- /dev/null
+++ b/src/test/java/g3401_3500/s3498_reverse_degree_of_a_string/SolutionTest.java
@@ -0,0 +1,18 @@
+package g3401_3500.s3498_reverse_degree_of_a_string;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+class SolutionTest {
+ @Test
+ void reverseDegree() {
+ assertThat(new Solution().reverseDegree("abc"), equalTo(148));
+ }
+
+ @Test
+ void reverseDegree2() {
+ assertThat(new Solution().reverseDegree("zaza"), equalTo(160));
+ }
+}
diff --git a/src/test/java/g3401_3500/s3499_maximize_active_section_with_trade_i/SolutionTest.java b/src/test/java/g3401_3500/s3499_maximize_active_section_with_trade_i/SolutionTest.java
new file mode 100644
index 000000000..eb30b637f
--- /dev/null
+++ b/src/test/java/g3401_3500/s3499_maximize_active_section_with_trade_i/SolutionTest.java
@@ -0,0 +1,28 @@
+package g3401_3500.s3499_maximize_active_section_with_trade_i;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+class SolutionTest {
+ @Test
+ void maxActiveSectionsAfterTrade() {
+ assertThat(new Solution().maxActiveSectionsAfterTrade("01"), equalTo(1));
+ }
+
+ @Test
+ void maxActiveSectionsAfterTrade2() {
+ assertThat(new Solution().maxActiveSectionsAfterTrade("0100"), equalTo(4));
+ }
+
+ @Test
+ void maxActiveSectionsAfterTrade3() {
+ assertThat(new Solution().maxActiveSectionsAfterTrade("1000100"), equalTo(7));
+ }
+
+ @Test
+ void maxActiveSectionsAfterTrade4() {
+ assertThat(new Solution().maxActiveSectionsAfterTrade("01010"), equalTo(4));
+ }
+}
diff --git a/src/test/java/g3401_3500/s3500_minimum_cost_to_divide_array_into_subarrays/SolutionTest.java b/src/test/java/g3401_3500/s3500_minimum_cost_to_divide_array_into_subarrays/SolutionTest.java
new file mode 100644
index 000000000..e32f9c9e2
--- /dev/null
+++ b/src/test/java/g3401_3500/s3500_minimum_cost_to_divide_array_into_subarrays/SolutionTest.java
@@ -0,0 +1,26 @@
+package g3401_3500.s3500_minimum_cost_to_divide_array_into_subarrays;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+class SolutionTest {
+ @Test
+ void minimumCost() {
+ assertThat(
+ new Solution().minimumCost(new int[] {3, 1, 4}, new int[] {4, 6, 6}, 1),
+ equalTo(110L));
+ }
+
+ @Test
+ void minimumCost2() {
+ assertThat(
+ new Solution()
+ .minimumCost(
+ new int[] {4, 8, 5, 1, 14, 2, 2, 12, 1},
+ new int[] {7, 2, 8, 4, 2, 2, 1, 1, 2},
+ 7),
+ equalTo(985L));
+ }
+}
diff --git a/src/test/java/g3501_3600/s3501_maximize_active_section_with_trade_ii/SolutionTest.java b/src/test/java/g3501_3600/s3501_maximize_active_section_with_trade_ii/SolutionTest.java
new file mode 100644
index 000000000..85c253c5b
--- /dev/null
+++ b/src/test/java/g3501_3600/s3501_maximize_active_section_with_trade_ii/SolutionTest.java
@@ -0,0 +1,51 @@
+package g3501_3600.s3501_maximize_active_section_with_trade_ii;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+class SolutionTest {
+ @Test
+ void maxActiveSectionsAfterTrade() {
+ assertThat(
+ new Solution().maxActiveSectionsAfterTrade("01", new int[][] {{0, 1}}),
+ equalTo(List.of(1)));
+ }
+
+ @Test
+ void maxActiveSectionsAfterTrade2() {
+ assertThat(
+ new Solution()
+ .maxActiveSectionsAfterTrade(
+ "0100", new int[][] {{0, 3}, {0, 2}, {1, 3}, {2, 3}}),
+ equalTo(List.of(4, 3, 1, 1)));
+ }
+
+ @Test
+ void maxActiveSectionsAfterTrade3() {
+ assertThat(
+ new Solution()
+ .maxActiveSectionsAfterTrade(
+ "1000100", new int[][] {{1, 5}, {0, 6}, {0, 4}}),
+ equalTo(List.of(6, 7, 2)));
+ }
+
+ @Test
+ void maxActiveSectionsAfterTrade4() {
+ assertThat(
+ new Solution()
+ .maxActiveSectionsAfterTrade("01010", new int[][] {{0, 3}, {1, 4}, {1, 3}}),
+ equalTo(List.of(4, 4, 2)));
+ }
+
+ @Test
+ void maxActiveSectionsAfterTrade5() {
+ assertThat(
+ new Solution()
+ .maxActiveSectionsAfterTrade(
+ "10110111", new int[][] {{3, 7}, {4, 6}, {0, 6}}),
+ equalTo(List.of(6, 6, 8)));
+ }
+}
diff --git a/src/test/java/g3501_3600/s3502_minimum_cost_to_reach_every_position/SolutionTest.java b/src/test/java/g3501_3600/s3502_minimum_cost_to_reach_every_position/SolutionTest.java
new file mode 100644
index 000000000..f35e420d1
--- /dev/null
+++ b/src/test/java/g3501_3600/s3502_minimum_cost_to_reach_every_position/SolutionTest.java
@@ -0,0 +1,22 @@
+package g3501_3600.s3502_minimum_cost_to_reach_every_position;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+class SolutionTest {
+ @Test
+ void minCosts() {
+ assertThat(
+ new Solution().minCosts(new int[] {5, 3, 4, 1, 3, 2}),
+ equalTo(new int[] {5, 3, 3, 1, 1, 1}));
+ }
+
+ @Test
+ void minCosts2() {
+ assertThat(
+ new Solution().minCosts(new int[] {1, 2, 4, 6, 7}),
+ equalTo(new int[] {1, 1, 1, 1, 1}));
+ }
+}
diff --git a/src/test/java/g3501_3600/s3503_longest_palindrome_after_substring_concatenation_i/SolutionTest.java b/src/test/java/g3501_3600/s3503_longest_palindrome_after_substring_concatenation_i/SolutionTest.java
new file mode 100644
index 000000000..42b8f4c5e
--- /dev/null
+++ b/src/test/java/g3501_3600/s3503_longest_palindrome_after_substring_concatenation_i/SolutionTest.java
@@ -0,0 +1,28 @@
+package g3501_3600.s3503_longest_palindrome_after_substring_concatenation_i;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+class SolutionTest {
+ @Test
+ void longestPalindrome() {
+ assertThat(new Solution().longestPalindrome("a", "a"), equalTo(2));
+ }
+
+ @Test
+ void longestPalindrome2() {
+ assertThat(new Solution().longestPalindrome("abc", "def"), equalTo(1));
+ }
+
+ @Test
+ void longestPalindrome3() {
+ assertThat(new Solution().longestPalindrome("b", "aaaa"), equalTo(4));
+ }
+
+ @Test
+ void longestPalindrome4() {
+ assertThat(new Solution().longestPalindrome("abcde", "ecdba"), equalTo(5));
+ }
+}
diff --git a/src/test/java/g3501_3600/s3504_longest_palindrome_after_substring_concatenation_ii/SolutionTest.java b/src/test/java/g3501_3600/s3504_longest_palindrome_after_substring_concatenation_ii/SolutionTest.java
new file mode 100644
index 000000000..846ced21e
--- /dev/null
+++ b/src/test/java/g3501_3600/s3504_longest_palindrome_after_substring_concatenation_ii/SolutionTest.java
@@ -0,0 +1,33 @@
+package g3501_3600.s3504_longest_palindrome_after_substring_concatenation_ii;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+class SolutionTest {
+ @Test
+ void longestPalindrome() {
+ assertThat(new Solution().longestPalindrome("a", "a"), equalTo(2));
+ }
+
+ @Test
+ void longestPalindrome2() {
+ assertThat(new Solution().longestPalindrome("abc", "def"), equalTo(1));
+ }
+
+ @Test
+ void longestPalindrome3() {
+ assertThat(new Solution().longestPalindrome("b", "aaaa"), equalTo(4));
+ }
+
+ @Test
+ void longestPalindrome4() {
+ assertThat(new Solution().longestPalindrome("abcde", "ecdba"), equalTo(5));
+ }
+
+ @Test
+ void longestPalindrome5() {
+ assertThat(new Solution().longestPalindrome("xxz", "z"), equalTo(2));
+ }
+}
diff --git a/src/test/java/g3501_3600/s3505_minimum_operations_to_make_elements_within_k_subarrays_equal/SolutionTest.java b/src/test/java/g3501_3600/s3505_minimum_operations_to_make_elements_within_k_subarrays_equal/SolutionTest.java
new file mode 100644
index 000000000..56a825923
--- /dev/null
+++ b/src/test/java/g3501_3600/s3505_minimum_operations_to_make_elements_within_k_subarrays_equal/SolutionTest.java
@@ -0,0 +1,21 @@
+package g3501_3600.s3505_minimum_operations_to_make_elements_within_k_subarrays_equal;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.junit.jupiter.api.Test;
+
+class SolutionTest {
+ @Test
+ void minOperations() {
+ assertThat(
+ new Solution().minOperations(new int[] {5, -2, 1, 3, 7, 3, 6, 4, -1}, 3, 2),
+ equalTo(8L));
+ }
+
+ @Test
+ void minOperations2() {
+ assertThat(
+ new Solution().minOperations(new int[] {9, -2, -2, -2, 1, 5}, 2, 2), equalTo(3L));
+ }
+}