- Identify the ordered answer range or sorted search domain.
- Write a predicate whose truth changes only once.
- Move the appropriate boundary after each midpoint check and return the final feasible position.
Code notes
- 180 lines of C++ from the credited upstream file threshold-majority-queries.cpp.
- The implementation visibly relies on sequence storage, hash lookup.
- 13 loop blocks detected.
Complexity
Multiply the logarithmic number of midpoint checks by the cost of one predicate evaluation.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
123 45class Solution {6public:7 vector<int> subarrayMajority(vector<int>& nums, vector<vector<int>>& queries) {8 vector<int> sorted_nums(nums);9 sort(begin(sorted_nums), end(sorted_nums));10 sorted_nums.erase(unique(begin(sorted_nums), end(sorted_nums)), end(sorted_nums));11 unordered_map<int, int> num_to_idx;12 for (int i = 0; i < size(sorted_nums); ++i) {13 num_to_idx[sorted_nums[i]] = i;14 } 15 16 17 const auto& mo_s_algorithm = [&]() {18 vector<int> cnt(size(num_to_idx));19 vector<int> cnt2(size(nums) + 1);20 int max_freq = 0;21 const auto& add = [&](int i) {22 const auto& idx = num_to_idx[nums[i]];23 if (cnt[idx]) {24 --cnt2[cnt[idx]];25 }26 ++cnt[idx];27 ++cnt2[cnt[idx]];28 max_freq = max(max_freq, cnt[idx]);29 };30 31 const auto& remove = [&](int i) {32 const auto& idx = num_to_idx[nums[i]];33 --cnt2[cnt[idx]];34 if (!cnt2[max_freq]) {35 --max_freq;36 }37 --cnt[idx];38 if (cnt[idx]) {39 ++cnt2[cnt[idx]];40 }41 };42 43 const auto& get_ans = [&](int t) {44 if (max_freq < t) {45 return -1;46 }47 int i = 0;48 for (; i < size(cnt); ++i) {49 if (cnt[i] == max_freq) {50 break;51 }52 }53 return sorted_nums[i];54 };55 56 vector<int> result(size(queries), -1);57 const int block_size = sqrt(size(nums)) + 1;58 vector<int> idxs(size(queries));59 iota(begin(idxs), end(idxs), 0);60 sort(begin(idxs), end(idxs), [&](const auto& a, const auto& b) {61 const auto& i = queries[a][0] / block_size;62 const auto& j = queries[b][0] / block_size;63 return i != j ? i < j : (i & 1 ? queries[a][1] < queries[b][1] : queries[a][1] > queries[b][1]);64 });65 int left = 0, right = -1;66 for (const auto& i : idxs) {67 const auto& l = queries[i][0];68 const auto& r = queries[i][1];69 const auto& t = queries[i][2];70 while (left > l) {71 left -= 1;72 add(left);73 }74 while (right < r) {75 ++right;76 add(right);77 }78 while (left < l) {79 remove(left);80 ++left;81 }82 while (right > r) {83 remove(right);84 --right;85 }86 result[i] = get_ans(t);87 }88 return result;89 };90 91 return mo_s_algorithm();92 }93};94 95969798class Solution2 {99public:100 vector<int> subarrayMajority(vector<int>& nums, vector<vector<int>>& queries) {101 vector<int> sorted_nums(nums);102 sort(begin(sorted_nums), end(sorted_nums));103 sorted_nums.erase(unique(begin(sorted_nums), end(sorted_nums)), end(sorted_nums));104 unordered_map<int, int> num_to_idx;105 for (int i = 0; i < size(sorted_nums); ++i) {106 num_to_idx[sorted_nums[i]] = i;107 } 108 109 110 const auto& mo_s_algorithm = [&]() {111 vector<int> cnt(size(num_to_idx));112 vector<multiset<int>> lookup(size(nums) + 1);113 int max_freq = 0;114 const auto& add = [&](int i) {115 const auto& idx = num_to_idx[nums[i]];116 if (cnt[idx]) {117 auto it = lookup[cnt[idx]].find(nums[i]);118 lookup[cnt[idx]].erase(it);119 }120 ++cnt[idx];121 lookup[cnt[idx]].emplace(nums[i]);122 max_freq = max(max_freq, cnt[idx]);123 };124 125 const auto& remove = [&](int i) {126 const auto& idx = num_to_idx[nums[i]];127 auto it = lookup[cnt[idx]].find(nums[i]);128 lookup[cnt[idx]].erase(it);129 if (empty(lookup[max_freq])) {130 --max_freq;131 }132 --cnt[idx];133 if (cnt[idx]) {134 lookup[cnt[idx]].emplace(nums[i]);135 }136 };137 138 const auto& get_ans = [&](int t) {139 return max_freq >= t ? *begin(lookup[max_freq]) : -1;140 };141 142 vector<int> result(size(queries), -1);143 const int block_size = sqrt(size(nums)) + 1;144 vector<int> idxs(size(queries));145 iota(begin(idxs), end(idxs), 0);146 sort(begin(idxs), end(idxs), [&](const auto& a, const auto& b) {147 const auto& i = queries[a][0] / block_size;148 const auto& j = queries[b][0] / block_size;149 return i != j ? i < j : (i & 1 ? queries[a][1] < queries[b][1] : queries[a][1] > queries[b][1]);150 });151 int left = 0, right = -1;152 for (const auto& i : idxs) {153 const auto& l = queries[i][0];154 const auto& r = queries[i][1];155 const auto& t = queries[i][2];156 while (left > l) {157 left -= 1;158 add(left);159 }160 while (right < r) {161 ++right;162 add(right);163 }164 while (left < l) {165 remove(left);166 ++left;167 }168 while (right > r) {169 remove(right);170 --right;171 }172 result[i] = get_ans(t);173 }174 return result;175 };176 177 return mo_s_algorithm();178 }179};180