|
1 | 1 | package g3601_3700.s3661_maximum_walls_destroyed_by_robots; |
2 | 2 |
|
3 | | -// #Hard #Weekly_Contest_464 #2025_08_24_Time_164_ms_(100.00%)_Space_59.97_MB_(100.00%) |
| 3 | +// #Hard #Weekly_Contest_464 #2025_08_29_Time_88_ms_(99.25%)_Space_68.62_MB_(40.75%) |
4 | 4 |
|
5 | 5 | import java.util.Arrays; |
6 | 6 |
|
7 | 7 | public class Solution { |
8 | 8 | public int maxWalls(int[] robots, int[] distance, int[] walls) { |
9 | | - int n = robots.length; |
10 | | - // Pair robots with distances and sort |
11 | | - int[][] rpair = new int[n][2]; |
12 | | - for (int i = 0; i < n; i++) { |
13 | | - rpair[i][0] = robots[i]; |
14 | | - rpair[i][1] = distance[i]; |
| 9 | + if (robots.length == 1) { |
| 10 | + int a = 0; |
| 11 | + int b = 0; |
| 12 | + for (int wall : walls) { |
| 13 | + if (wall < robots[0] - distance[0] || wall > robots[0] + distance[0]) { |
| 14 | + continue; |
| 15 | + } |
| 16 | + if (wall < robots[0]) { |
| 17 | + a++; |
| 18 | + } else if (wall > robots[0]) { |
| 19 | + b++; |
| 20 | + } else { |
| 21 | + a++; |
| 22 | + b++; |
| 23 | + } |
| 24 | + } |
| 25 | + return Math.max(a, b); |
15 | 26 | } |
16 | | - Arrays.sort(rpair, (a, b) -> Integer.compare(a[0], b[0])); |
17 | | - int[] r = new int[n]; |
18 | | - int[] d = new int[n]; |
19 | | - for (int i = 0; i < n; i++) { |
20 | | - r[i] = rpair[i][0]; |
21 | | - d[i] = rpair[i][1]; |
| 27 | + int[][] arr = new int[robots.length][]; |
| 28 | + for (int i = 0; i < robots.length; i++) { |
| 29 | + arr[i] = new int[] {robots[i], distance[i]}; |
22 | 30 | } |
| 31 | + Arrays.sort(arr, (a, b) -> a[0] - b[0]); |
23 | 32 | Arrays.sort(walls); |
24 | | - // Count walls at robot positions |
25 | | - int base = 0; |
26 | | - for (int i = 0; i < n; i++) { |
27 | | - int idx = Arrays.binarySearch(walls, r[i]); |
28 | | - if (idx >= 0) { |
29 | | - base++; |
30 | | - } |
| 33 | + int a = 0; |
| 34 | + int b = 0; |
| 35 | + int i = 0; |
| 36 | + int j = 0; |
| 37 | + while (i < walls.length && walls[i] < arr[j][0] - arr[j][1]) { |
| 38 | + i++; |
31 | 39 | } |
32 | | - // Tail walls |
33 | | - int leftTail = countRange(walls, (long) r[0] - d[0], r[0] - 1L); |
34 | | - int rightTail = countRange(walls, r[n - 1] + 1L, (long) r[n - 1] + d[n - 1]); |
35 | | - // Precompute segment ranges |
36 | | - int segs = n - 1; |
37 | | - int max = Math.max(0, segs); |
38 | | - int[] a = new int[max]; |
39 | | - int[] b = new int[max]; |
40 | | - int[] c = new int[max]; |
41 | | - for (int i = 0; i < segs; i++) { |
42 | | - int segL = r[i] + 1; |
43 | | - int segR = r[i + 1] - 1; |
44 | | - if (segL > segR) { |
45 | | - a[i] = b[i] = c[i] = 0; |
46 | | - continue; |
47 | | - } |
48 | | - int aHigh = Math.min(segR, r[i] + d[i]); |
49 | | - a[i] = countRange(walls, segL, aHigh); |
50 | | - int bLow = Math.max(segL, r[i + 1] - d[i + 1]); |
51 | | - b[i] = countRange(walls, bLow, segR); |
52 | | - int cLow = Math.max(segL, r[i + 1] - d[i + 1]); |
53 | | - int cHigh = Math.min(segR, r[i] + d[i]); |
54 | | - c[i] = countRange(walls, cLow, cHigh); |
| 40 | + while (i < walls.length && walls[i] <= arr[j][0]) { |
| 41 | + a++; |
| 42 | + i++; |
55 | 43 | } |
56 | | - int[][] dp = new int[n][2]; |
57 | | - Arrays.fill(dp[0], Integer.MIN_VALUE / 4); |
58 | | - // first fires left |
59 | | - dp[0][0] = base + leftTail; |
60 | | - // first fires right |
61 | | - dp[0][1] = base; |
62 | | - for (int i = 0; i < n - 1; i++) { |
63 | | - Arrays.fill(dp[i + 1], Integer.MIN_VALUE / 4); |
64 | | - for (int choice = 0; choice <= 1; choice++) { |
65 | | - int cur = dp[i][choice]; |
66 | | - if (cur < 0) { |
67 | | - continue; |
68 | | - } |
69 | | - int addIfNextLeft = (choice == 1) ? a[i] + b[i] - c[i] : b[i]; |
70 | | - dp[i + 1][0] = Math.max(dp[i + 1][0], cur + addIfNextLeft); |
71 | | - int addIfNextRight = (choice == 1) ? a[i] : 0; |
72 | | - dp[i + 1][1] = Math.max(dp[i + 1][1], cur + addIfNextRight); |
73 | | - } |
| 44 | + if (i > 0 && walls[i - 1] == arr[j][0]) { |
| 45 | + i--; |
74 | 46 | } |
75 | | - int res; |
76 | | - if (n == 1) { |
77 | | - res = Math.max(dp[0][0], dp[0][1] + rightTail); |
78 | | - } else { |
79 | | - res = Math.max(dp[n - 1][0], dp[n - 1][1] + rightTail); |
| 47 | + while (i < walls.length && walls[i] <= arr[j][0] + arr[j][1] && walls[i] < arr[j + 1][0]) { |
| 48 | + b++; |
| 49 | + i++; |
80 | 50 | } |
81 | | - return res; |
82 | | - } |
83 | | - |
84 | | - private int countRange(int[] arr, long l, long r) { |
85 | | - if (l > r || arr.length == 0) { |
86 | | - return 0; |
87 | | - } |
88 | | - int leftIdx = lowerBound(arr, l); |
89 | | - int rightIdx = upperBound(arr, r); |
90 | | - return Math.max(0, rightIdx - leftIdx); |
91 | | - } |
92 | | - |
93 | | - private int lowerBound(int[] a, long x) { |
94 | | - int l = 0; |
95 | | - int r = a.length; |
96 | | - while (l < r) { |
97 | | - int m = (l + r) >>> 1; |
98 | | - if (a[m] < x) { |
99 | | - l = m + 1; |
100 | | - } else { |
101 | | - r = m; |
| 51 | + j++; |
| 52 | + while (j < arr.length) { |
| 53 | + int l1 = 0; |
| 54 | + int k = i; |
| 55 | + while (k < walls.length && walls[k] < arr[j][0] - arr[j][1]) { |
| 56 | + k++; |
102 | 57 | } |
103 | | - } |
104 | | - return l; |
105 | | - } |
106 | | - |
107 | | - private int upperBound(int[] a, long x) { |
108 | | - int l = 0; |
109 | | - int r = a.length; |
110 | | - while (l < r) { |
111 | | - int m = (l + r) >>> 1; |
112 | | - if (a[m] <= x) { |
113 | | - l = m + 1; |
| 58 | + while (k < walls.length && walls[k] <= arr[j][0]) { |
| 59 | + l1++; |
| 60 | + k++; |
| 61 | + } |
| 62 | + int nextI = k; |
| 63 | + int l2 = l1; |
| 64 | + k = i - 1; |
| 65 | + while (k >= 0 && walls[k] > arr[j - 1][0] && walls[k] >= arr[j][0] - arr[j][1]) { |
| 66 | + l2++; |
| 67 | + k--; |
| 68 | + } |
| 69 | + int aNext = Math.max(a + l2, b + l1); |
| 70 | + int r = 0; |
| 71 | + int lim = |
| 72 | + j < arr.length - 1 |
| 73 | + ? Math.min(arr[j + 1][0], arr[j][0] + arr[j][1] + 1) |
| 74 | + : arr[j][0] + arr[j][1] + 1; |
| 75 | + if (nextI > 0 && walls[nextI - 1] == arr[j][0]) { |
| 76 | + i = nextI - 1; |
114 | 77 | } else { |
115 | | - r = m; |
| 78 | + i = nextI; |
| 79 | + } |
| 80 | + while (i < walls.length && walls[i] < lim) { |
| 81 | + r++; |
| 82 | + i++; |
116 | 83 | } |
| 84 | + j++; |
| 85 | + int bNext = Math.max(a, b) + r; |
| 86 | + a = aNext; |
| 87 | + b = bNext; |
117 | 88 | } |
118 | | - return l; |
| 89 | + return Math.max(a, b); |
119 | 90 | } |
120 | 91 | } |
0 commit comments