Skip to content

Commit 7ed6245

Browse files
authored
Improved tasks 3161, 3327
1 parent 89649d4 commit 7ed6245

File tree

2 files changed

+148
-139
lines changed
  • src/main/java

2 files changed

+148
-139
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,107 +1,112 @@
11
package g3101_3200.s3161_block_placement_queries;
22

33
// #Hard #Array #Binary_Search #Segment_Tree #Binary_Indexed_Tree
4-
// #2024_05_30_Time_137_ms_(99.38%)_Space_143.7_MB_(54.52%)
4+
// #2025_03_16_Time_47_ms_(100.00%)_Space_144.38_MB_(56.41%)
55

6-
import java.util.ArrayList;
6+
import java.util.Arrays;
77
import java.util.List;
88

99
public class Solution {
10-
private static class Seg {
11-
private final int start;
12-
private final int end;
13-
private int min;
14-
private int max;
15-
private int len;
16-
private boolean obstacle;
17-
private Seg left;
18-
private Seg right;
19-
20-
public static Seg init(int n) {
21-
return new Seg(0, n);
22-
}
23-
24-
private Seg(int start, int end) {
25-
this.start = start;
26-
this.end = end;
27-
if (start >= end) {
28-
return;
10+
public List<Boolean> getResults(int[][] queries) {
11+
int m = queries.length;
12+
int[] pos = new int[m + 1];
13+
int size = 0;
14+
pos[size++] = 0;
15+
int max = 0;
16+
for (int[] q : queries) {
17+
max = Math.max(max, q[1]);
18+
if (q[0] == 1) {
19+
pos[size++] = q[1];
2920
}
30-
int mid = start + ((end - start) >> 1);
31-
left = new Seg(start, mid);
32-
right = new Seg(mid + 1, end);
33-
refresh();
3421
}
22+
Arrays.sort(pos, 0, size);
23+
max++;
24+
UnionFind left = new UnionFind(max + 1);
25+
UnionFind right = new UnionFind(max + 1);
26+
BIT bit = new BIT(max);
27+
initializePositions(size, pos, bit, left, right, max);
28+
return List.of(getBooleans(queries, m, size, left, right, bit));
29+
}
3530

36-
public void set(int i) {
37-
if (i < start || i > end) {
38-
return;
39-
} else if (i == start && i == end) {
40-
obstacle = true;
41-
min = max = start;
42-
return;
31+
private void initializePositions(
32+
int size, int[] pos, BIT bit, UnionFind left, UnionFind right, int max) {
33+
for (int i = 1; i < size; i++) {
34+
int pre = pos[i - 1];
35+
int cur = pos[i];
36+
bit.update(cur, cur - pre);
37+
for (int j = pre + 1; j < cur; j++) {
38+
left.parent[j] = pre;
39+
right.parent[j] = cur;
4340
}
44-
left.set(i);
45-
right.set(i);
46-
refresh();
4741
}
42+
for (int j = pos[size - 1] + 1; j < max; j++) {
43+
left.parent[j] = pos[size - 1];
44+
right.parent[j] = max;
45+
}
46+
}
4847

49-
private void refresh() {
50-
if (left.obstacle) {
51-
min = left.min;
52-
if (right.obstacle) {
53-
max = right.max;
54-
len = Math.max(right.min - left.max, Math.max(left.len, right.len));
55-
} else {
56-
max = left.max;
57-
len = Math.max(left.len, right.end - left.max);
58-
}
59-
obstacle = true;
60-
} else if (right.obstacle) {
61-
min = right.min;
62-
max = right.max;
63-
len = Math.max(right.len, right.min - left.start);
64-
obstacle = true;
48+
private Boolean[] getBooleans(
49+
int[][] queries, int m, int size, UnionFind left, UnionFind right, BIT bit) {
50+
Boolean[] ans = new Boolean[m - size + 1];
51+
int index = ans.length - 1;
52+
for (int i = m - 1; i >= 0; i--) {
53+
int[] q = queries[i];
54+
int x = q[1];
55+
int pre = left.find(x - 1);
56+
if (q[0] == 1) {
57+
int next = right.find(x + 1);
58+
left.parent[x] = pre;
59+
right.parent[x] = next;
60+
bit.update(next, next - pre);
6561
} else {
66-
len = end - start;
62+
int maxGap = Math.max(bit.query(pre), x - pre);
63+
ans[index--] = maxGap >= q[2];
6764
}
6865
}
66+
return ans;
67+
}
68+
69+
private static final class BIT {
70+
int n;
71+
int[] tree;
6972

70-
public void max(int n, int[] t) {
71-
if (end <= n) {
72-
t[0] = Math.max(t[0], len);
73-
if (obstacle) {
74-
t[1] = max;
75-
}
76-
return;
73+
public BIT(int n) {
74+
this.n = n;
75+
tree = new int[n];
76+
}
77+
78+
public void update(int i, int v) {
79+
while (i < n) {
80+
tree[i] = Math.max(tree[i], v);
81+
i += i & -i;
7782
}
78-
left.max(n, t);
79-
if (!right.obstacle || right.min >= n) {
80-
return;
83+
}
84+
85+
public int query(int i) {
86+
int result = 0;
87+
while (i > 0) {
88+
result = Math.max(result, tree[i]);
89+
i &= i - 1;
8190
}
82-
t[0] = Math.max(t[0], right.min - t[1]);
83-
right.max(n, t);
91+
return result;
8492
}
8593
}
8694

87-
public List<Boolean> getResults(int[][] queries) {
88-
int max = 0;
89-
for (int[] i : queries) {
90-
max = Math.max(max, i[1]);
95+
private static final class UnionFind {
96+
private final int[] parent;
97+
98+
public UnionFind(int n) {
99+
parent = new int[n];
100+
for (int i = 1; i < n; i++) {
101+
parent[i] = i;
102+
}
91103
}
92-
Seg root = Seg.init(max);
93-
root.set(0);
94104

95-
List<Boolean> res = new ArrayList<>(queries.length);
96-
for (int[] i : queries) {
97-
if (i[0] == 1) {
98-
root.set(i[1]);
99-
} else {
100-
int[] t = new int[2];
101-
root.max(i[1], t);
102-
res.add(Math.max(t[0], i[1] - t[1]) >= i[2]);
105+
public int find(int x) {
106+
if (parent[x] != x) {
107+
parent[x] = find(parent[x]);
103108
}
109+
return parent[x];
104110
}
105-
return res;
106111
}
107112
}
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,80 @@
11
package g3301_3400.s3327_check_if_dfs_strings_are_palindromes;
22

33
// #Hard #Array #String #Hash_Table #Depth_First_Search #Tree #Hash_Function
4-
// #2024_10_22_Time_159_ms_(90.40%)_Space_93.9_MB_(80.80%)
5-
6-
import java.util.ArrayList;
7-
import java.util.List;
4+
// #2025_03_16_Time_70_ms_(100.00%)_Space_75.50_MB_(96.67%)
85

96
public class Solution {
10-
private final List<List<Integer>> e = new ArrayList<>();
11-
private final StringBuilder stringBuilder = new StringBuilder();
12-
private String s;
13-
private int now;
14-
private int n;
15-
private int[] l;
16-
private int[] r;
17-
private int[] p;
18-
private char[] c;
7+
private int time = 0;
8+
private byte[] cs;
9+
private int[][] graph;
1910

20-
private void dfs(int x) {
21-
l[x] = now + 1;
22-
for (int v : e.get(x)) {
23-
dfs(v);
11+
public boolean[] findAnswer(int[] parent, String s) {
12+
int n = s.length();
13+
cs = s.getBytes();
14+
graph = new int[n][];
15+
final int[] childCount = new int[n];
16+
for (int i = 1; i < n; i++) {
17+
childCount[parent[i]]++;
2418
}
25-
stringBuilder.append(s.charAt(x));
26-
r[x] = ++now;
27-
}
28-
29-
private void matcher() {
30-
c[0] = '~';
31-
c[1] = '#';
32-
for (int i = 1; i <= n; ++i) {
33-
c[2 * i + 1] = '#';
34-
c[2 * i] = stringBuilder.charAt(i - 1);
19+
for (int i = 0; i < n; i++) {
20+
graph[i] = new int[childCount[i]];
21+
childCount[i] = 0;
3522
}
36-
int j = 1;
37-
int mid = 0;
38-
int localR = 0;
39-
while (j <= 2 * n + 1) {
40-
if (j <= localR) {
41-
p[j] = Math.min(p[(mid << 1) - j], localR - j + 1);
42-
}
43-
while (c[j - p[j]] == c[j + p[j]]) {
44-
++p[j];
45-
}
46-
if (p[j] + j > localR) {
47-
localR = p[j] + j - 1;
48-
mid = j;
49-
}
50-
++j;
23+
for (int i = 1; i < n; i++) {
24+
graph[parent[i]][childCount[parent[i]]++] = i;
25+
}
26+
byte[] dfsStr = new byte[n];
27+
int[] start = new int[n];
28+
int[] end = new int[n];
29+
dfs(0, dfsStr, start, end);
30+
int[] lens = getRadius(dfsStr);
31+
boolean[] ans = new boolean[n];
32+
for (int i = 0; i < n; i++) {
33+
int l = start[i];
34+
int r = end[i];
35+
int center = l + r + 2;
36+
ans[i] = lens[center] >= r - l + 1;
5137
}
38+
return ans;
5239
}
5340

54-
public boolean[] findAnswer(int[] parent, String s) {
55-
n = parent.length;
56-
this.s = s;
57-
for (int i = 0; i < n; ++i) {
58-
e.add(new ArrayList<>());
41+
private void dfs(int u, byte[] dfsStr, int[] start, int[] end) {
42+
start[u] = time;
43+
for (int v : graph[u]) {
44+
dfs(v, dfsStr, start, end);
5945
}
60-
for (int i = 1; i < n; ++i) {
61-
e.get(parent[i]).add(i);
46+
dfsStr[time] = cs[u];
47+
end[u] = time++;
48+
}
49+
50+
private int[] getRadius(byte[] cs) {
51+
int n = cs.length;
52+
byte[] t = new byte[2 * n + 3];
53+
int m = 0;
54+
t[m++] = '@';
55+
t[m++] = '#';
56+
for (byte c : cs) {
57+
t[m++] = c;
58+
t[m++] = '#';
6259
}
63-
l = new int[n];
64-
r = new int[n];
65-
dfs(0);
66-
c = new char[2 * n + 10];
67-
p = new int[2 * n + 10];
68-
matcher();
69-
boolean[] ans = new boolean[n];
70-
for (int i = 0; i < n; ++i) {
71-
int mid = (2 * r[i] - 2 * l[i] + 1) / 2 + 2 * l[i];
72-
ans[i] = p[mid] - 1 >= r[i] - l[i] + 1;
60+
t[m++] = '$';
61+
int[] lens = new int[m];
62+
int center = 0;
63+
int right = 0;
64+
for (int i = 2; i < m - 2; i++) {
65+
int len = 0;
66+
if (i < right) {
67+
len = Math.min(lens[2 * center - i], right - i);
68+
}
69+
while (t[i + len + 1] == t[i - len - 1]) {
70+
len++;
71+
}
72+
if (right < i + len) {
73+
right = i + len;
74+
center = i;
75+
}
76+
lens[i] = len;
7377
}
74-
return ans;
78+
return lens;
7579
}
7680
}

0 commit comments

Comments
 (0)