1
+ import java .util .ArrayList ;
2
+ import java .util .Arrays ;
3
+ import java .util .Collections ;
4
+ import java .util .HashMap ;
5
+ import java .util .HashSet ;
6
+ import java .util .List ;
7
+ import java .util .Map ;
8
+ import java .util .Set ;
9
+ import java .util .TreeMap ;
10
+ import java .util .TreeSet ;
11
+
12
+ public class Solution3636 {
13
+ public int [] subarrayMajority (int [] nums , int [][] queries ) {
14
+ int n = nums .length ;
15
+ int numQueries = queries .length ;
16
+
17
+ Set <Integer > set = new HashSet <>();
18
+ for (int num : nums ) {
19
+ set .add (num );
20
+ }
21
+ List <Integer > list = new ArrayList <>(set );
22
+ Collections .sort (list );
23
+ Map <Integer , Integer > numToIdx = new HashMap <>();
24
+ for (int i = 0 ; i < list .size (); i ++) {
25
+ numToIdx .put (list .get (i ), i );
26
+ }
27
+
28
+ int m = list .size ();
29
+ int [] arr = new int [n ];
30
+ for (int i = 0 ; i < n ; i ++) {
31
+ arr [i ] = numToIdx .get (nums [i ]);
32
+ }
33
+
34
+ int blockSize = (int ) Math .sqrt (n );
35
+ Query [] qs = new Query [numQueries ];
36
+ for (int i = 0 ; i < numQueries ; i ++) {
37
+ int l = queries [i ][0 ];
38
+ int r = queries [i ][1 ];
39
+ int threshold = queries [i ][2 ];
40
+ qs [i ] = new Query (l , r , threshold , i );
41
+ }
42
+
43
+ Arrays .sort (qs , (a , b ) -> {
44
+ int blockA = a .l / blockSize ;
45
+ int blockB = b .l / blockSize ;
46
+ if (blockA != blockB ) {
47
+ return blockA - blockB ;
48
+ }
49
+ if (blockA % 2 == 0 ) {
50
+ return a .r - b .r ;
51
+ } else {
52
+ return b .r - a .r ;
53
+ }
54
+ });
55
+
56
+ int [] cnt = new int [m ];
57
+ TreeMap <Integer , TreeSet <Integer >> freqToNums = new TreeMap <>();
58
+ int left = 0 , right = -1 ;
59
+ int [] ans = new int [numQueries ];
60
+
61
+ for (Query query : qs ) {
62
+ int l = query .l , r = query .r , threshold = query .threshold , idx = query .idx ;
63
+ while (right < r ) {
64
+ add (arr [++right ], cnt , freqToNums );
65
+ }
66
+ while (right > r ) {
67
+ remove (arr [right --], cnt , freqToNums );
68
+ }
69
+ while (left < l ) {
70
+ remove (arr [left ++], cnt , freqToNums );
71
+ }
72
+ while (left > l ) {
73
+ add (arr [--left ], cnt , freqToNums );
74
+ }
75
+
76
+ int maxFreq = freqToNums .isEmpty () ? 0 : freqToNums .lastKey ();
77
+ if (maxFreq < threshold ) {
78
+ ans [idx ] = -1 ;
79
+ } else {
80
+ int numIdx = freqToNums .get (maxFreq ).first ();
81
+ ans [idx ] = list .get (numIdx );
82
+ }
83
+ }
84
+
85
+ return ans ;
86
+ }
87
+
88
+ private void add (int x , int [] cnt , TreeMap <Integer , TreeSet <Integer >> freqToNums ) {
89
+ int oldFreq = cnt [x ];
90
+ int newFreq = oldFreq + 1 ;
91
+ cnt [x ] = newFreq ;
92
+
93
+ if (oldFreq > 0 ) {
94
+ TreeSet <Integer > setOld = freqToNums .get (oldFreq );
95
+ setOld .remove (x );
96
+ if (setOld .isEmpty ()) {
97
+ freqToNums .remove (oldFreq );
98
+ }
99
+ }
100
+
101
+ TreeSet <Integer > setNew = freqToNums .computeIfAbsent (newFreq , k -> new TreeSet <>());
102
+ setNew .add (x );
103
+ }
104
+
105
+ private void remove (int x , int [] cnt , TreeMap <Integer , TreeSet <Integer >> freqToNums ) {
106
+ int oldFreq = cnt [x ];
107
+ int newFreq = oldFreq - 1 ;
108
+ cnt [x ] = newFreq ;
109
+
110
+ TreeSet <Integer > setOld = freqToNums .getOrDefault (oldFreq , new TreeSet <>());
111
+ setOld .remove (x );
112
+ if (setOld .isEmpty ()) {
113
+ freqToNums .remove (oldFreq );
114
+ }
115
+
116
+ if (newFreq > 0 ) {
117
+ TreeSet <Integer > setNew = freqToNums .computeIfAbsent (newFreq , k -> new TreeSet <>());
118
+ setNew .add (x );
119
+ }
120
+ }
121
+
122
+ static class Query {
123
+ int l , r , threshold , idx ;
124
+
125
+ Query (int l , int r , int threshold , int idx ) {
126
+ this .l = l ;
127
+ this .r = r ;
128
+ this .threshold = threshold ;
129
+ this .idx = idx ;
130
+ }
131
+ }
132
+ }
133
+ /*
134
+ 3636. 查询超过阈值频率最高元素
135
+ https://leetcode.cn/problems/threshold-majority-queries/description/
136
+
137
+ 第 162 场双周赛 T4。
138
+
139
+ 给你一个长度为 n 的整数数组 nums 和一个查询数组 queries,其中 queries[i] = [li, ri, thresholdi]。
140
+ 返回一个整数数组 ans,其中 ans[i] 等于子数组 nums[li...ri] 中出现 至少 thresholdi 次的元素,选择频率 最高 的元素(如果频率相同则选择 最小 的元素),如果不存在这样的元素则返回 -1。
141
+ 提示:
142
+ 1 <= nums.length == n <= 10^4
143
+ 1 <= nums[i] <= 10^9
144
+ 1 <= queries.length <= 5 * 10^4
145
+ queries[i] = [li, ri, thresholdi]
146
+ 0 <= li <= ri < n
147
+ 1 <= thresholdi <= ri - li + 1
148
+
149
+ 离散化 + 莫队算法。
150
+ 莫队是轮椅算法(轮椅是指在稍有挑战性的游戏中,玩家可以使用的,攻略易复制的,上手难度低,强度超标的武器装备,或者某种套路,这些装备和套路可以大幅度地提高技术水平较低的玩家的游玩体验)。
151
+ 时间复杂度 O((n + q) sqrt(n) logm)。其中n为数组长度,q为查询数量,m为不同数字个数。
152
+ 莫队算法(回滚莫队)https://leetcode.cn/problems/threshold-majority-queries/solutions/3740919/mo-dui-suan-fa-hui-gun-mo-dui-pythonjava-x7yw/
153
+ https://chat.deepseek.com/a/chat/s/83972666-2ebb-4b37-bb65-646f15179fec
154
+ rating 2325 (clist.by)
155
+ */
0 commit comments