Data structure to handle numerous queries on large size array - data-structures

Given q queries of the following form. A list is there.
1 x y: Add number x to the list y times.
2 n: find the nth number of the sorted list
constraints
1 <= q <= 5 * 100000
1 <= x, y <= 1000000000
1 <= n < length of list
sample.
input
4
1 3 6
1 5 2
2 7
2 4
output
5
3

This is a competitive programming problem that it's too early in the morning for me to solve right now, but I can try and give some pointers.
If you were to store the entire array explicitly, it would obviously blow out your memory. But you can exploit the structure of the array to instead store the number of times each entry appears in the array. So if you got the query
1 3 5
then instead of storing [3, 3, 3], you'd store the pair (3, 5), indicating that the number 3 is in the list 5 times.
You can pretty easily build this, perhaps as a vector of pairs of ints that you update.
The remaining task is to implement the 2 query, where you find an element by its index. A side effect of the structure we've chosen is that you can't directly index into that vector of pairs of ints, since the indices in that list don't match up with the indices into the hypothetical array. We could just add up the size of each entry in the vector from the start until we hit the index we want, but that's O(n^2) in the number of queries we've processed so far... likely too slow. Instead, we probably want some updatable data structure for prefix sums—perhaps as described in this answer.

Related

Algorithms: Get final state of array after incrementing/decrementing elements based on neighbors

You're given an array of integers A. You keep doing iterations of the following until the array stops changing: if an element is larger than both of its adjacent neighbors, decrement it by 1. If an element is smaller than both of its adjacent neighbors, increment it by 1. Return the final state of the array (when it will not change any more). Note that the first and last elements do not have two neighbors, so they will never change.
Example: [1,2,7,4,6] -> [1,2,6,5,6] ->[1,2,5,6,6]
Example: [1,2,3,4] Does not change
Anyone have an idea of how to do this better than simulation? I feel like there should be an O(n) solution, but I can't think of it.
You can calculate teh differnce between all numbers. For your series:
1 , 2 , 7 , 4 , 6 you get
1 5 -3 2
you can conclude that a sign change from + to - means a decrease of the number and from - to + and increase
You also can conclude that 7 can be decreased min(abs(5), abs(-3)) = 3 times max before it "hits its boundry" what is 4. Problem is that 4 changes with the first iteration. This you can recognize by the 2 sequential sign changes. So when this is happening, your max before hitting the boudry for 7 becomes: min(abs(5), ceiling(abs(-3)/2)) = 2
as the max of hitting the boundy on 4 becomes min(ceiling(abs(-3)/2), abs(2)) = 2
With the knowledge above, you know you need to deduct: 7 - 2 = 5 and increase 4 + 2 = 6 to get your answer.

How to perform range updates in sqrt{n} time?

I have an array and I have to perform query and updates on it.
For queries, I have to find frequency of a particular number in a range from l to r and for update, I have to add x from some range l to r.
How to perform this?
I thought of sqrt{n} optimization but I don't know how to perform range updates with this time complexity.
Edit - Since some people are asking for an example, here is one
Suppose the array is of size n = 8
and it is
1 3 3 4 5 1 2 3
And there are 3 queries to help everybody explain about what I am trying to say
Here they are
q 1 5 3 - This means that you have to find the frequency of 3 in range 1 to 5 which is 2 as 3 appears on 2nd and 3rd position.
second is update query and it goes like this - u 2 4 6 -> This means that you have to add 6 in the array from range 2 to 4. So the new array will become
1 9 9 10 5 1 2 3
And the last query is again the same as first one which will now return 0 as there is no 3 in the array from position 1 to 5 now.
I believe things must be more clear now. :)
I developed this algorithm long time (20+ years) ago for Arithmetic coder.
Both Update and Retrieve are performed in O(log(N)).
I named this algorithm "Method of Intervals". Let I show you the example.
Imagine, we have 8 intervals, with numbers 0-7:
+--0--+--1--+--2-+--3--+--4--+--5--+--6--+--7--+
Lets we create additional set of intervals, each spawns pair of original ones:
+----01-----+----23----+----45-----+----67-----+
Thereafter, we'll create the extra one layer of intervals, spawn pairs of 2nd:
+---------0123---------+---------4567----------+
And at last, we create single interval, covers all 8:
+------------------01234567--------------------+
As you see, in this structure, to retrieve right border of the interval [5], you needed just add together length of intervals [0123] + [45]. to retrieve left border of the interval [5], you needed sum of length the intervals [0123] + [4] (left border for 5 is right border for 4).
Of course, left border of the interval [0] is always = 0.
When you'll watch this proposed structure carefully, you will see, the odd elements in the each layers aren't needed. I say, you do not needed elements 1, 3, 5, 7, 23, 67, 4567, since these elements aren't used, during Retrieval or Update.
Lets we remove the odd elements and make following remuneration:
+--1--+--x--+--3-+--x--+--5--+--x--+--7--+--x--+
+-----2-----+-----x----+-----6-----+-----x-----+
+-----------4----------+-----------x-----------+
+----------------------8-----------------------+
As you see, with this remuneration, used the numbers [1-8]. Lets they will be array indexes. So, you see, there is used memory O(N).
To retrieve right border of the interval [7], you needed add length of the values with indexes 4,6,7. To update length of the interval [7], you needed add difference to all 3 of these values. As result, both Retrieval and Update are performed for Log(N) time.
Now is needed algorithm, how by the original interval number compute set of indexes in this data structure. For instance - how to convert:
1 -> 1
2 -> 2
3 -> 3,2
...
7 -> 7,6,4
This is easy, if we will see binary representation for these numbers:
1 -> 1
10 -> 10
11 -> 11,10
111 -> 111,110,100
As you see, in the each chain - next value is previous value, where rightmost "1" changed to "0". Using simple bit operation "x & (x - 1)", we can wtite a simple loop to iterate array indexes, related to the interval number:
int interval = 7;
do {
int index = interval;
do_something(index);
} while(interval &= interval - 1);

Determining the Longest Continguous Subsequence

There are N nodes (1 <= N <= 100,000) various positions along a
long one-dimensional length. The ith node is at position x_i (an
integer in the range 0...1,000,000,000) and has a node type b_i(an integer in
the range 1..8). Nodes can not be in the same position
You want to get a range on this one-dimension in which all of the types of nodes are fairly represented. Therefore, you want to ensure that, for whatever types of nodes that are present in the range, there is an equal number of each node type (for example, a range with 27 each of types 1 and 3 is ok, a range with 27 of types 1, 3, and 4 is
ok, but 9 of type 1 and 10 of type 3 is not ok). You also want
at least K (K >= 2) types (out of the 8 total) to be represented in the
rand. Find the maximum size of this range that satisfies the constraints. The size of a photo is the difference between the maximum and minimum positions of the nodes in the photo.
If there are no ranges satisfying the constraints, output -1 instead.
INPUT:
* Line 1: N and K separated by a space
* Lines 2..N+1: Each line contains a description of a node as two
integers separated by a space; x(i) and its node type.
INPUT:
9 2
1 1
5 1
6 1
9 1
100 1
2 2
7 2
3 3
8 3
INPUT DETAILS:
Node types: 1 2 3 - 1 1 2 3 1 - ... - 1
Locations: 1 2 3 4 5 6 7 8 9 10 ... 99 100
OUTPUT:
* Line 1: A single integer indicating the maximum size of a fair
range. If no such range exists, output -1.
OUTPUT:
6
OUTPUT DETAILS:
The range from x = 2 to x = 8 has 2 each of types 1, 2, and 3. The range
from x = 9 to x = 100 has 2 of type 1, but this is invalid because K = 2
and so you need at least 2 distinct types of nodes.
Could You Please help in suggesting some algorithm to solve this. I have thought about using some sort of priority queue or stack data structure, but am really unsure how to proceed.
Thanks, Todd
It's not too difficult to invent almost linear-time algorithm because recently similar problem was discussed on CodeChef: "ABC-Strings".
Sort nodes by their positions.
Prepare all possible subsets of node types (for example, we could expect types 1,2,4,5,7 to be present in resulting interval and all other types not present there). For K=2 there may be only 256-8-1=247 subsets. For each subset perform remaining steps:
Initialize 8 type counters to [0,0,0,0,0,0,0,0].
For each node perform remaining steps:
Increment counter for current node type.
Take L counters for types included to current subset, subtract first of them from other L-1 counters, which produces L-1 values. Take remaining 8-L counters and combine them together with those L-1 values into a tuple of 7 values.
Use this tuple as a key for hash map. If hash map contains no value for this key, add a new entry with this key and value equal to the position of current node. Otherwise subtract value in the hash map from the position of current node and (possibly) update the best result.

Update the range in an array

Given an array of length N.I need to perform certain operations on this array, these operations are of two types:
Update a range [x...y]: In which we must divide each number in the given range [x...y] by K.(This division is integer division)
Query a range [x...y]: In which we must output the sum of all the numbers presently in range [x...y].
Example : Let say we have N=5 ,K=2 and array is {1,1,1,1,5} .let we have Q(=5) queries as follow :
2 1 5
1 1 2
2 1 5
1 5 5
2 1 5
Then in this Output will be :
9
7
4
Now I know to solve it for smaller number of queries but how to do it if Q and N are large.
I don't get your question precisely.But I understand about querying...
->When you are running multiple queries on inputs like these
For Example:
If you have 1st query in range [2000,10000] and second one in range [2000,4000]
you end up adding these numbers multiple times,which is bad.
->Try using the concept of cumulative frequencies.
Ex:
1. Compute the cumulative sum for all indexes [0...n-1] in Array.
2. Now, When you need sum for a certain query [x...y] then just do
Array[y]-Array[x-1].....which would be direct result.
3. Believe me this would save you lot of computation.
4. This concept is similar to Dynamic Programming(try Googling it!!)

How to display unique numbers with their frequencies as occurring in a matrix?

I have a matrice with some number:
1 2 3 6
6 7 2 1
1 4 5 6
And the program should display all different number with own frequency for example:
1 -> 3
2 -> 2
3 -> 1
4 -> 1
5 -> 1
6 -> 3
7 -> 1
Please help me
You probably mean
1->3
Create vector (array), filled with zeros, that have size of max value in matrice (like [0..9]), travell by whole matrice and with every step increment index of vector that equals actual number.
This is soluction for short range values in matrice. If you excpect some big values, use joined list insted of vector, or matrice like this for counting:
1 0
5 0
15 0
142 0
2412 0
And increment values in second column and expand this matrice rows every time you find a new number.
Using pointers this problem reduces from matrix to a single dimensional array. Maintain a 1D array whose size is equal to the total no. of elements in the matrix, say it COUNT. Initialize it with zero. Now start with first element of the matrix and compare it with all the other elements. If we use pointers this problem transforms into traversing a 1D array and finding the no of occurrences of each element. For traversing all you have to do is just increment the pointer. While comparing when you encounter the same number just shift forward all the consecutive numbers one place ahead. For example, if 0th element is 1 and you again found 1 on 4th index, then shift forward element on 5th index to 4th, 6th to 5th and so on till the last element. This way the duplicate entry at 4th index is lost. Now decrease the count of total no of elements in the matrix by 1 and increase the corresponding entry in array COUNT by 1. Continuing this way till the last element we get a matrix with distinct nos. and their corresponding frequency in array COUNT.
This implementation is very effective for languages which support pointers.
Here's an example of how it could be done in Python.
The dict is of this format: {key:value, key2:value2}. So you can use that so you have something like {'2':3} so it'll tell you what number has how many occurances. (I'm not assuming you're going to use Python. It's just so you understand the code... maybe)
matrix = [[1,5,6],
[2,6,3],
[5,3,9]]
dict = {}
for row in matrix:
for column in row:
if str(column) in dict.keys():
dict[str(column)] += 1
else:
dict[str(column)] = 1
for key in sorted(dict.keys()):
print key, '->', dict[key]
I hope you can figure out what this does. This codepad shows the output and nice syntax hightlighting.
(I don't get why SO isn't aligning the code properly... it's monospaced but not aligned :S ... turns out it's because I was using IE6 (It's the only browser at work :-(

Resources