Skip to content

Commit a36113e

Browse files
committed
Improved tasks 3477-3480
1 parent 7f40c67 commit a36113e

File tree

5 files changed

+149
-94
lines changed
  • src
    • main/kotlin/g3401_3500
    • test/kotlin/g3401_3500/s3480_maximize_subarrays_after_removing_one_conflicting_pair

5 files changed

+149
-94
lines changed
Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,23 @@
11
package g3401_3500.s3477_fruits_into_baskets_ii
22

33
// #Easy #Array #Binary_Search #Simulation #Segment_Tree
4-
// #2025_03_10_Time_4_ms_(100.00%)_Space_47.71_MB_(100.00%)
4+
// #2025_03_11_Time_3_ms_(100.00%)_Space_47.78_MB_(75.61%)
55

66
class Solution {
77
fun numOfUnplacedFruits(fruits: IntArray, baskets: IntArray): Int {
88
val n = fruits.size
9-
var ct = 0
10-
val used = BooleanArray(n)
11-
for (fruit in fruits) {
12-
var flag = true
13-
for (i in 0..<n) {
14-
if (fruit <= baskets[i] && !used[i]) {
15-
used[i] = true
16-
flag = false
9+
var currfruits: Int
10+
var count = 0
11+
for (i in 0..<n) {
12+
currfruits = fruits[i]
13+
for (j in 0..<n) {
14+
if (baskets[j] >= currfruits) {
15+
count++
16+
baskets[j] = 0
1717
break
1818
}
1919
}
20-
if (flag) {
21-
ct++
22-
}
2320
}
24-
return ct
21+
return n - count
2522
}
2623
}
Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,40 @@
11
package g3401_3500.s3478_choose_k_elements_with_maximum_sum
22

33
// #Medium #Array #Sorting #Heap_Priority_Queue
4-
// #2025_03_10_Time_238_ms_(100.00%)_Space_87.94_MB_(100.00%)
4+
// #2025_03_11_Time_151_ms_(100.00%)_Space_93.64_MB_(40.74%)
55

66
import java.util.PriorityQueue
77

88
class Solution {
99
fun findMaxSum(nums1: IntArray, nums2: IntArray, k: Int): LongArray {
1010
val n = nums1.size
11-
val arr = Array<IntArray>(n) { IntArray(3) }
12-
for (i in 0..<n) {
13-
arr[i][0] = nums1[i]
14-
arr[i][1] = nums2[i]
15-
arr[i][2] = i
16-
}
17-
arr.sortWith { a: IntArray, b: IntArray -> a[0] - b[0] }
1811
val ans = LongArray(n)
19-
val pq = PriorityQueue<Int>()
20-
var sum: Long = 0
21-
for (i in 0..<n) {
22-
if (i > 0 && arr[i - 1][0] == arr[i][0]) {
23-
ans[arr[i][2]] = ans[arr[i - 1][2]]
24-
} else {
25-
ans[arr[i][2]] = sum
12+
val ps = Array<Point>(n) { i -> Point(nums1[i], nums2[i], i) }
13+
ps.sortWith { p1: Point, p2: Point -> p1.x.compareTo(p2.x) }
14+
val pq = PriorityQueue<Int?>()
15+
var s: Long = 0
16+
var i = 0
17+
while (i < n) {
18+
var j = i
19+
while (j < n && ps[j].x == ps[i].x) {
20+
ans[ps[j].i] = s
21+
j++
2622
}
27-
pq.add(arr[i][1])
28-
sum += arr[i][1].toLong()
29-
if (pq.size > k) {
30-
sum -= pq.remove()!!.toLong()
23+
for (p in i..<j) {
24+
val cur = ps[p].y
25+
if (pq.size < k) {
26+
pq.offer(cur)
27+
s += cur.toLong()
28+
} else if (cur > pq.peek()!!) {
29+
s -= pq.poll()!!.toLong()
30+
pq.offer(cur)
31+
s += cur.toLong()
32+
}
3133
}
34+
i = j
3235
}
3336
return ans
3437
}
38+
39+
private class Point(var x: Int, var y: Int, var i: Int)
3540
}
Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,53 @@
11
package g3401_3500.s3479_fruits_into_baskets_iii
22

33
// #Medium #Array #Binary_Search #Ordered_Set #Segment_Tree
4-
// #2025_03_10_Time_555_ms_(100.00%)_Space_78.68_MB_(100.00%)
4+
// #2025_03_11_Time_53_ms_(92.86%)_Space_86.21_MB_(7.14%)
55

66
import kotlin.math.max
77

88
class Solution {
99
fun numOfUnplacedFruits(fruits: IntArray, baskets: IntArray): Int {
10-
var unp = 0
11-
var max = 0
12-
val list: MutableList<Int> = ArrayList<Int>()
13-
for (basket in baskets) {
14-
list.add(basket)
15-
max = max(max, basket)
10+
val n = baskets.size
11+
var size = 1
12+
while (size < n) {
13+
size = size shl 1
1614
}
17-
for (fruit in fruits) {
18-
if (fruit > max) {
19-
unp++
15+
val seg = IntArray(2 * size)
16+
for (i in 0..<n) {
17+
seg[size + i] = baskets[i]
18+
}
19+
for (i in n..<size) {
20+
seg[size + i] = 0
21+
}
22+
for (i in size - 1 downTo 1) {
23+
seg[i] = max(seg[i shl 1].toDouble(), seg[i shl 1 or 1].toDouble()).toInt()
24+
}
25+
var ans = 0
26+
for (f in fruits) {
27+
if (seg[1] < f) {
28+
ans++
2029
continue
2130
}
22-
var placed = false
23-
for (j in list.indices) {
24-
if (list[j] >= fruit) {
25-
list.removeAt(j)
26-
placed = true
27-
break
31+
var idx = 1
32+
while (idx < size) {
33+
if (seg[idx shl 1] >= f) {
34+
idx = idx shl 1
35+
} else {
36+
idx = idx shl 1 or 1
2837
}
2938
}
30-
if (!placed) {
31-
unp++
32-
}
39+
update(seg, idx - size, 0, size)
40+
}
41+
return ans
42+
}
43+
44+
private fun update(seg: IntArray, pos: Int, `val`: Int, size: Int) {
45+
var i = pos + size
46+
seg[i] = `val`
47+
i /= 2
48+
while (i > 0) {
49+
seg[i] = max(seg[i shl 1].toDouble(), seg[i shl 1 or 1].toDouble()).toInt()
50+
i /= 2
3351
}
34-
return unp
3552
}
3653
}
Lines changed: 70 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,86 @@
11
package g3401_3500.s3480_maximize_subarrays_after_removing_one_conflicting_pair
22

33
// #Hard #Array #Prefix_Sum #Enumeration #Segment_Tree
4-
// #2025_03_10_Time_742_ms_(100.00%)_Space_165.07_MB_(100.00%)
4+
// #2025_03_11_Time_48_ms_(100.00%)_Space_164.15_MB_(100.00%)
55

6-
import java.util.TreeMap
76
import kotlin.math.max
7+
import kotlin.math.min
88

99
class Solution {
10-
fun maxSubarrays(n: Int, cp: Array<IntArray>): Long {
11-
for (pair in cp) {
12-
if (pair[0] > pair[1]) {
13-
val temp = pair[0]
14-
pair[0] = pair[1]
15-
pair[1] = temp
10+
fun maxSubarrays(n: Int, conflictingPairs: Array<IntArray>): Long {
11+
val totalSubarrays = n.toLong() * (n + 1) / 2
12+
val h = IntArray(n + 1)
13+
val d2 = IntArray(n + 1)
14+
h.fill(n + 1)
15+
d2.fill(n + 1)
16+
for (pair in conflictingPairs) {
17+
var a = pair[0]
18+
var b = pair[1]
19+
if (a > b) {
20+
val temp = a
21+
a = b
22+
b = temp
1623
}
24+
if (b < h[a]) {
25+
d2[a] = h[a]
26+
h[a] = b
27+
} else if (b < d2[a]) {
28+
d2[a] = b
29+
}
30+
}
31+
val f = IntArray(n + 2)
32+
f[n + 1] = n + 1
33+
f[n] = h[n]
34+
for (i in n - 1 downTo 1) {
35+
f[i] = min(h[i], f[i + 1]).toInt()
1736
}
18-
cp.sortWith { a: IntArray, b: IntArray -> a[0].compareTo(b[0]) }
19-
val contributions = LongArray(cp.size)
20-
var totalPossible = n.toLong() * (n + 1) / 2
21-
val endPointMap = TreeMap<Int, MutableList<Int>>()
22-
var currentIndex = cp.size - 1
23-
for (start in n downTo 1) {
24-
while (currentIndex >= 0 && cp[currentIndex][0] >= start) {
25-
val end = cp[currentIndex][1]
26-
endPointMap.computeIfAbsent(end) { _: Int -> ArrayList<Int>() }
27-
.add(currentIndex)
28-
currentIndex--
37+
// forbiddenCount(x) returns (n - x + 1) if x <= n, else 0.
38+
// This is the number of forbidden subarrays starting at some i when f[i] = x.
39+
var originalUnion: Long = 0
40+
for (i in 1..n) {
41+
if (f[i] <= n) {
42+
originalUnion += (n - f[i] + 1).toLong()
2943
}
30-
if (endPointMap.isEmpty()) {
44+
}
45+
val originalValid = totalSubarrays - originalUnion
46+
var best = originalValid
47+
// For each index j (1 <= j <= n) where a candidate conflicting pair exists,
48+
// simulate removal of the pair that gave h[j] (if any).
49+
// (If there is no candidate pair at j, h[j] remains n+1.)
50+
for (j in 1..n) {
51+
// no conflicting pair at index j
52+
if (h[j] == n + 1) {
3153
continue
3254
}
33-
val firstEntry = endPointMap.firstEntry()
34-
val smallestEnd: Int = firstEntry.key!!
35-
val pairIndex: Int = firstEntry.value!![0]
36-
if (firstEntry.value!!.size == 1) {
37-
endPointMap.remove(smallestEnd)
38-
} else {
39-
firstEntry.value!!.removeAt(0)
40-
}
41-
val covered = n - smallestEnd + 1L
42-
totalPossible -= covered
43-
if (endPointMap.isEmpty()) {
44-
contributions[pairIndex] += covered
45-
} else {
46-
val nextEnd: Int = endPointMap.firstKey()!!
47-
contributions[pairIndex] += (nextEnd - smallestEnd).toLong()
55+
// Simulate removal: new candidate at j becomes d2[j]
56+
val newCandidate = if (j < n) min(d2[j], f[j + 1]).toInt() else d2[j]
57+
// We'll recompute the new f values for indices 1..j.
58+
// Let newF[i] denote the updated value.
59+
// For i > j, newF[i] remains as original f[i].
60+
// For i = j, newF[j] = min( newCandidate, f[j+1] ) (which is newCandidate by
61+
// definition).
62+
val newFj = newCandidate
63+
// forbiddenCount(x) is defined as (n - x + 1) if x<= n, else 0.
64+
var delta = forbiddenCount(newFj, n) - forbiddenCount(f[j], n)
65+
var cur = newFj
66+
// Now update backwards for i = j-1 down to 1.
67+
for (i in j - 1 downTo 1) {
68+
val newVal = min(h[i], cur)
69+
// no further change for i' <= i
70+
if (newVal == f[i]) {
71+
break
72+
}
73+
delta += forbiddenCount(newVal, n) - forbiddenCount(f[i], n)
74+
cur = newVal
4875
}
49-
endPointMap.computeIfAbsent(smallestEnd) { _: Int -> ArrayList<Int>() }
50-
.add(pairIndex)
76+
val newUnion = originalUnion + delta
77+
val newValid = totalSubarrays - newUnion
78+
best = max(best, newValid)
5179
}
52-
var result = totalPossible
53-
for (contribution in contributions) {
54-
result = max(result, (totalPossible + contribution))
55-
}
56-
return result
80+
return best
81+
}
82+
83+
private fun forbiddenCount(x: Int, n: Int): Long {
84+
return (if (x <= n) (n - x + 1) else 0).toLong()
5785
}
5886
}

src/test/kotlin/g3401_3500/s3480_maximize_subarrays_after_removing_one_conflicting_pair/SolutionTest.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,12 @@ internal class SolutionTest {
3434
equalTo<Long>(50L),
3535
)
3636
}
37+
38+
@Test
39+
fun maxSubarrays4() {
40+
assertThat(
41+
Solution().maxSubarrays(25, arrayOf<IntArray>(intArrayOf(9, 7), intArrayOf(15, 7), intArrayOf(4, 7))),
42+
equalTo(216L),
43+
)
44+
}
3745
}

0 commit comments

Comments
 (0)