Find the number of elements greater than x in a given range
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Given an array and many queries, scanning each range from left to right is often too slow. A better solution preprocesses the data so each query can quickly count how many values in positions L through R are greater than a threshold x.
The Problem and the Naive Baseline
Suppose you have an array values and queries shaped like (left, right, x). For each query, you need the count of elements in that index range whose value is strictly greater than x.
The direct approach is simple:
This runs in linear time per query. If the array has n elements and you have many queries, the total cost can become too high.
Merge Sort Tree Approach
A practical data structure for this problem is a merge sort tree. It is a segment tree where each node stores the values of its segment in sorted order. To answer a query, you visit only the nodes that cover the requested range and use binary search in each node to count how many values are greater than x.
The preprocessing cost is O(n log n), and each query runs in O(log^2 n).
This is a strong choice when the array does not change and you need fast repeated queries.
Offline Queries With a Fenwick Tree
If updates are not required and all queries are known in advance, an offline strategy can be even cleaner. Sort array positions by value in descending order. Sort queries by x in descending order. As you move through the queries, activate every array position whose value is greater than the current x, then use a Fenwick tree to count how many active positions lie inside the requested index range.
That reduces each query to O(log n) after sorting. The main idea is that "greater than x" becomes a prefix of the values sorted in descending order.
This method is common in competitive programming because it is fast and memory-efficient, but it is less intuitive than a merge sort tree if you are learning the problem for the first time.
Choosing the Right Technique
Use the naive loop if the array is small or the number of queries is tiny. Use a merge sort tree when you want a reusable, query-friendly structure for many range requests. Use the offline Fenwick approach when all queries are available ahead of time and raw speed matters.
If the array also supports updates, the problem becomes harder. You would need a more advanced data structure such as a balanced binary indexed structure per segment, a wavelet tree, or a carefully designed ordered-statistics tree.
Common Pitfalls
- Forgetting whether the range endpoints are inclusive causes off-by-one errors immediately.
- Using
bisect_leftinstead ofbisect_rightchanges the behavior for values equal tox. - Building a merge sort tree for an empty array needs a guard case to avoid invalid recursion.
- Assuming the offline method works for dynamic updates is incorrect because its preprocessing depends on fixed data.
- Confusing value order with index order breaks Fenwick tree solutions.
Summary
- The naive solution is easy but costs linear time per query.
- A merge sort tree preprocesses sorted values per segment and answers each query in
O(log^2 n). - An offline Fenwick tree solution can reduce query time to
O(log n)when all queries are known in advance. - Binary search details matter because the problem asks for values strictly greater than
x. - Pick the data structure based on whether the array is static, whether updates exist, and how many queries you need to answer.

