Problem:
Given an array of n integers and q queries of the form: Q(L, R, x). For each query Q(L, R, x), you have to say "How many integers in the range L to R(inclusive) which are less than x".
There is no update operation.
Constraints:
- 1 ≤ n ≤ 1900000
- 1 ≤ q ≤ 105
I know two ways:
Using SQRT decompostion: Partition the array in SQRT(n) blocks and Sort each block. Then for each query binary search(lower bound or upper bound) x in each block. If I use Square Root Decomposition, complexity will be O(q * sqrt(n) * logn), which is not so good for this constraints, I think.
Using segment tree: Store the sorted list of numbers in each node in the segment tree. Then for each query, binary search x at each required node.
Can you please suggest any better solution for this problem ?
Thanks in advance.
You can make a segment tree, where each node is a ordered vector with the elements from l to r, then the search will be O(log^2)
If the left child contains: 1, 3, 5 and right child contains: 2, 4, 6, then the node will contains: 1, 2, 3, 4, 5, 6 ?
What will be the complexity of building the segment tree ?
The complexity it will be O(Nlog^2) to construction, and O(NlogN) to memory. The depth of the segment tree will at most log(N), each level will contain at most N elements The first level contain N elements, the second contain two nodes of N/2 elements, the third contain four nodes of N/4 elements, the level logN contain N nodes of 1 element
by the way, shouldn't the complexity to build be O(NlogN)?
yes, you're right
for more info, here's the link.
You can solve this problem offline using range trees as there are no update operations.
Compress all the values and than iterate through them (note that there will be at most n + q distinct values). At each iteration i add all the numbers equal to i to your range tree(add 1 to their initial position in array) and answer to all the queries where x = i.The answer to the query will be the sum of the numbers in the range tree from position l to r.
Thus the complexity is O((q + n) * log(n)).
I didn't get it. Sorry, I am not familiar with this technique.
Can you please explain more ?
http://blog.ezyang.com/2012/02/visualizing-range-trees/
First note 2 things.
Why the log n factor? Can you eliminate it? As there is no update, you can do it in O(1). Think about it.
EDIT If the range of the domain is too high. This won't work :(
If I eliminate log n factor, then in worst case, will it pass in 1 sec, for the given constraints?
Depends on the OJ. In CF, yes.
I am not able to find any way to eliminate log factor.
Since, x may be changed in every query, I should binary search x on each of the SQRT(n) sorted blocks.
How can I eliminate this log factor ?
You can use a persistent segment tree. Using it you can find the number of interesting integers on prefixes [0;L - 1] and [0;R]. Then you can easily compute the answer. Complexion is O(q * logn) both for time and memory.
I never used persistent segment tree before. So, if you explain the idea more clearly, it would be easier to understand for me.
Also beside anudeep's blog, is there any good resource to learn it easily?
I would be thankful to you !!
Well, the idea of the solution is to build sum ST over integer line. Once when we meet array element ai we add 1 to the corresponding vertex of segment tree. For every update, we should do a new ST version by adding log(N) new vertexes. Then, when getting the answer, we are going back to the versions L - 1 and R and getting prefix sums on segments [0;x).
Unfortunately, I don't really know good resources where persistent ST is explained. Well, I've learned segment tree from here. Unfortunately, it's only in Russian.
Since there is no need to update array I suppose that it is possible to solve this problem via preffix sum. Correct me if I am wrong.
How to solve this problem via prefix sum ? Can you please elaborate?
Create an array of n elements. If element in original array is less than x change value to 1. Then calculate preffix sum.
x is different for each query.
As there is no update operation, you can solve this problem using Sorting + BIT.
Auto comment: topic has been updated by shahidul_brur (previous revision, new revision, compare).
You can remove logn from your sqrt decomposition solution by compressing the numbers and using prefix sums instead of binary search.
I don't understand how to do it. Please explain it with example?