Skip to content

Commit 1af17c1

Browse files
committed
Improved task 3636
1 parent 54fac7e commit 1af17c1

File tree

1 file changed

+74
-104
lines changed
  • src/main/java/g3601_3700/s3636_threshold_majority_queries

1 file changed

+74
-104
lines changed
Lines changed: 74 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,133 +1,103 @@
11
package g3601_3700.s3636_threshold_majority_queries;
22

3-
// #Hard #Biweekly_Contest_162 #2025_08_03_Time_1027_ms_(_%)_Space_72.53_MB_(100.00%)
3+
// #Hard #Biweekly_Contest_162 #2025_08_06_Time_82_ms_(98.38%)_Space_71.28_MB_(74.76%)
44

55
import java.util.ArrayList;
6-
import java.util.HashMap;
6+
import java.util.Arrays;
77
import java.util.List;
8-
import java.util.Map;
9-
import java.util.TreeSet;
108

11-
@SuppressWarnings("java:S1210")
129
public class Solution {
10+
private int[] nums;
11+
private int[] indexToValue;
12+
private int[] cnt;
13+
private int maxCnt = 0;
14+
private int minVal = 0;
1315

14-
private static class FreqPair implements Comparable<FreqPair> {
15-
int count;
16-
int value;
17-
18-
public FreqPair(int count, int value) {
19-
this.count = count;
20-
this.value = value;
21-
}
22-
23-
@Override
24-
public int compareTo(FreqPair other) {
25-
if (this.count != other.count) {
26-
return Integer.compare(this.count, other.count);
27-
}
28-
return Integer.compare(other.value, this.value);
29-
}
30-
}
31-
32-
// A helper class to store a query's range and its original index.
3316
private static class Query {
17+
int bid;
3418
int l;
3519
int r;
36-
int originalIndex;
20+
int threshold;
21+
int qid;
3722

38-
public Query(int l, int r, int idx) {
23+
Query(int bid, int l, int r, int threshold, int qid) {
24+
this.bid = bid;
3925
this.l = l;
4026
this.r = r;
41-
this.originalIndex = idx;
42-
}
43-
}
44-
45-
private int[] nums;
46-
private Map<Integer, Integer> counts;
47-
private TreeSet<FreqPair> sortedFrequencies;
48-
49-
private void add(int pos) {
50-
int val = this.nums[pos];
51-
int oldCount = this.counts.getOrDefault(val, 0);
52-
if (oldCount > 0) {
53-
this.sortedFrequencies.remove(new FreqPair(oldCount, val));
54-
}
55-
int newCount = oldCount + 1;
56-
this.counts.put(val, newCount);
57-
this.sortedFrequencies.add(new FreqPair(newCount, val));
58-
}
59-
60-
private void remove(int pos) {
61-
int val = this.nums[pos];
62-
int oldCount = this.counts.get(val);
63-
this.sortedFrequencies.remove(new FreqPair(oldCount, val));
64-
int newCount = oldCount - 1;
65-
if (newCount > 0) {
66-
this.counts.put(val, newCount);
67-
this.sortedFrequencies.add(new FreqPair(newCount, val));
68-
} else {
69-
this.counts.remove(val);
27+
this.threshold = threshold;
28+
this.qid = qid;
7029
}
7130
}
7231

7332
public int[] subarrayMajority(int[] nums, int[][] queries) {
74-
this.nums = nums;
75-
this.counts = new HashMap<>();
76-
this.sortedFrequencies = new TreeSet<>();
7733
int n = nums.length;
78-
int qLen = queries.length;
79-
List<Query> queryList = new ArrayList<>();
80-
int[] thresholds = new int[qLen];
81-
for (int i = 0; i < qLen; i++) {
82-
queryList.add(new Query(queries[i][0], queries[i][1], i));
83-
thresholds[i] = queries[i][2];
84-
}
85-
int blockSize = 1;
86-
if (qLen > 0) {
87-
blockSize = Math.max(1, (int) (n / Math.sqrt(qLen)));
34+
int m = queries.length;
35+
this.nums = nums;
36+
cnt = new int[n + 1];
37+
int[] nums2 = nums.clone();
38+
Arrays.sort(nums2);
39+
indexToValue = new int[n];
40+
for (int i = 0; i < n; i++) {
41+
indexToValue[i] = Arrays.binarySearch(nums2, nums[i]);
8842
}
89-
final int finalBlockSize = blockSize;
90-
queryList.sort(
91-
(a, b) -> {
92-
int blockA = a.l / finalBlockSize;
93-
int blockB = b.l / finalBlockSize;
94-
if (blockA != blockB) {
95-
return Integer.compare(blockA, blockB);
96-
}
97-
if ((blockA % 2) == 1) {
98-
return Integer.compare(b.r, a.r);
99-
} else {
100-
return Integer.compare(a.r, b.r);
101-
}
102-
});
103-
104-
int[] ans = new int[qLen];
105-
int currentL = 0;
106-
int currentR = -1;
107-
for (Query q : queryList) {
108-
while (currentL > q.l) {
109-
add(--currentL);
43+
int[] ans = new int[m];
44+
int blockSize = (int) Math.ceil(n / Math.sqrt(m));
45+
List<Query> qs = new ArrayList<>();
46+
for (int i = 0; i < m; i++) {
47+
int[] q = queries[i];
48+
int l = q[0];
49+
int r = q[1] + 1;
50+
int threshold = q[2];
51+
if (r - l > blockSize) {
52+
qs.add(new Query(l / blockSize, l, r, threshold, i));
53+
continue;
11054
}
111-
while (currentR < q.r) {
112-
add(++currentR);
55+
for (int j = l; j < r; j++) {
56+
add(j);
11357
}
114-
while (currentL < q.l) {
115-
remove(currentL++);
58+
ans[i] = maxCnt >= threshold ? minVal : -1;
59+
for (int j = l; j < r; j++) {
60+
cnt[indexToValue[j]]--;
11661
}
117-
while (currentR > q.r) {
118-
remove(currentR--);
62+
maxCnt = 0;
63+
}
64+
qs.sort((a, b) -> a.bid != b.bid ? a.bid - b.bid : a.r - b.r);
65+
int r = 0;
66+
for (int i = 0; i < qs.size(); i++) {
67+
Query q = qs.get(i);
68+
int l0 = (q.bid + 1) * blockSize;
69+
if (i == 0 || q.bid > qs.get(i - 1).bid) {
70+
r = l0;
71+
Arrays.fill(cnt, 0);
72+
maxCnt = 0;
73+
}
74+
for (; r < q.r; r++) {
75+
add(r);
76+
}
77+
int tmpMaxCnt = maxCnt;
78+
int tmpMinVal = minVal;
79+
for (int j = q.l; j < l0; j++) {
80+
add(j);
11981
}
120-
if (sortedFrequencies.isEmpty()) {
121-
ans[q.originalIndex] = -1;
122-
} else {
123-
FreqPair mostFrequent = sortedFrequencies.last();
124-
if (mostFrequent.count >= thresholds[q.originalIndex]) {
125-
ans[q.originalIndex] = mostFrequent.value;
126-
} else {
127-
ans[q.originalIndex] = -1;
128-
}
82+
ans[q.qid] = maxCnt >= q.threshold ? minVal : -1;
83+
maxCnt = tmpMaxCnt;
84+
minVal = tmpMinVal;
85+
for (int j = q.l; j < l0; j++) {
86+
cnt[indexToValue[j]]--;
12987
}
13088
}
13189
return ans;
13290
}
91+
92+
private void add(int i) {
93+
int v = indexToValue[i];
94+
int c = ++cnt[v];
95+
int x = nums[i];
96+
if (c > maxCnt) {
97+
maxCnt = c;
98+
minVal = x;
99+
} else if (c == maxCnt) {
100+
minVal = Math.min(minVal, x);
101+
}
102+
}
133103
}

0 commit comments

Comments
 (0)