Complexity of range sum query in a quad tree - c++

I want to solve a problem that gives the (integral) coordinates of n points (n<=10^5)
and asks q queries (q<=10^4). In each query it gives the (integral) coordinates of two other points and we need to answer how many of the n points are located within the rectangle created by those two points.
(edit) Also the coordinates are huge (x,y <= 10^9) (/edit)
I created a quad tree and then used this function to get the answer, however i get time limit exceeded (time limit = 2s). Is this approach too slow or have I done something wrong?
int sum(int left, int right, int down, int up, int i=1, int begx=0, int endx=1e9, int begy=0, int endy=1e9)
{
if (!i || left>right || down>up) return 0;
if (left==begx && right==endx && down==begy && up==endy) return num[i];
int midx = (begx+endx)/2, midy = (begy+endy)/2;
return sum(left,min(midx,right),down,min(midy,up),child[i][0],begx,midx,begy,midy)
+ sum(left,min(midx,right),max(midy+1,down),up,child[i][1],begx,midx,midy+1,endy)
+ sum(max(midx+1,left),right,down,min(midy,up),child[i][2],midx+1,endx,begy,midy)
+ sum(max(midx+1,left),right,max(midy+1,down),up,child[i][3],midx+1,endx,midy+1,endy);
}
If I comment this function out (and don't answer the queries, just add the points to the quad tree) I get an execution time of about 0.2 secs.
Array num stores the sum of a node and child stores the index of the four children of each node. Node 0 is dummy. The partitioning of a rectangle in children looks like this:
___
|1 3|
|0 2|
---

Related

Find the summation of forces between all possible pairs of points?

There are n points with each having two attributes:
1. Position (from axis)
2. Attraction value (integer)
Attraction force between two points A & B is given by:
Attraction_force(A, B) = (distance between them) * Max(Attraction_val_A, Attraction_val_B);
Find the summation of all the forces between all possible pairs of points?
I tried by calculating and adding forces between all the pairs
for(int i=0; i<n-1; i++) {
for(int j=i+1; j<n; j++) {
force += abs(P[i].pos - P[j].pos) * max(P[i].attraction_val, P[j].attraction_val);
}
}
Example:
Points P1 P2 P3
Points distance: 2 3 4
Attraction Val: 4 5 6
Force = abs(2 - 3) * max(4, 5) + abs(2 - 4) * max(4, 6) + abs(3 - 4) * max(5, 6) = 23
But this takes O(n^2) time, I can't think of a way to reduce it further!!
Scheme of a solution:
Sort all points by their attraction value and process them one-by-one, starting with the one with lowest attraction.
For each point you have to quickly calculate sum of distances to all previously added points. That can be done using any online Range Sum Query problem solution, like segment tree or BIT. Key idea is that all points to the left are really not different and sum of their coordinates is enough to calculate sum of distances to them.
For each newly added point you just multiply that sum of distances (obtained on step 2) by point's attraction value and add that to the answer.
Intuitive observations that I made in order to invent this solution:
We have two "bad" functions here (somewhat "discrete"): max and modulo (in distance).
We can get rid of max by sorting our points and processing them in a specific order.
We can get rid of modulo if we process points to the left and to the right separately.
After all these transformations, we have to calculate something which, after some simple algebraic transformations, converts to an online RSQ problem.
An algorithm of:
O(N2)
is optimal, because you need the actual distance between all possible pairs.

Belman-Ford algorithm in 2d Array

I've got a problem with applying a Bellman-Ford algorithm to 2D Array (not to graph)
Input array has m x n dimensions:
s[1,1] s[1,2] ... s[1,n] -> Exit
s[2,1] s[2,2] ... s[2,n]
...
Entry -> s[m,1] s[m,2] ... s[m,n]
And it is room-alike (each entry is a room with s[x,y] cost of enterance). Each room could have also a negative cost, and we have to find cheapest path from Entry to choosen room and to Exit.
For example, we've got this array of rooms and costs:
1 5 6
2 -3 4
5 2 -8
And we want to walk over room [3,2], s[3,2] = 4. We are starting form 5 at [1,3] and must walk over [3,2] before we go to [3,3].
And my question is, what is the best way to implement it in Bellman-Ford algorithm? I know that Dijkstry algorithm will not work becouse of negative cost.
Is for each room from [0, maxHeight] and relax all neighbors correct? Like this:
for (int i = height-1; i >= 0; --i) {
for (int j = 0; j < width; ++j) {
int x = i;
int y = j;
if (x > 0) // up
Relax(x, y, x - 1, y);
if (y + 1 < width) // right
Relax(x, y, x, y + 1);
if (y > 0) // left
Relax(x, y, x, y - 1);
if (x + 1 < height) // down
Relax(x, y, x + 1, y);
}
}
But how can I then read a cost to choosen room and from room to exit?
If you know how to move on the graph from an array, you can scroll to additional condition paragraph. Read also next paragraph.
In fact, you can look at that building like on a graph.
You can see like: (I forgot doors in second line, sorry.)
So, how it is possible to be implement. Ignore for the moment additional condition (visit a particular vertex before leaving).
Weight function:
Let S[][] be an array of entry cost. Notice, that about weight of edge decides only vertex on the end. It has no matter if it's (1, 2) -> (1,3) or (2,3) -> (1, 3). Cost is defined by second vertex. so function may look like:
cost_type cost(vertex v, vertex w) {
return S[w.y][w.x];
}
//As you can see, first argument is unnecessary.
Edges:
In fact you don't have to keep all edges in some array. You can calculate them in function every time you need.
The neighbours for vertex (x, y) are (x+1, y), (x-1, y), (x, y+1), (x, y-1), if that nodes exist. You have to check it, but it's easy. (Check if new_x > 0 && new_x < max_x.) It may look like that:
//Size of matrix is M x N
is_correct(vertex w) {
if(w.y < 1 || w.y > M || w.x < 1 || w.x > N) {
return INCORRECT;
}
return CORRECT;
}
Generating neighbours can look like:
std::tie(x, y) = std::make_tuple(v.x, v.y);
for(vertex w : {{x+1, y}, {x-1, y}, {x, y+1}, {x, y-1}}) {
if(is_correct(w) == CORRECT) {//CORRECT may be true
relax(v, w);
}
}
I believe, that it shouldn't take extra memory for four edges. If you don't know std::tie, look at cppreference. (Extra variables x, y take more memory, but I believe that it's more readable here. In your code it may not appear.)
Obviously you have to have other 2D array with distance and (if necessary) predecessor, but I think it's clear and I don't have to describe it.
Additional condition:
You want to know cost from enter to exit, but you have to visit some vertex compulsory. Easiest way to calculate it is to calculate cost from enter to compulsory and from compulsory to exit. (There will be two separate calculations.) It will not change big O time. After that you can just add results.
You just have to guarantee that it's impossible to visit exit before compulsory. It's easy, you can just erase outgoing edges from exit by adding extra line in is_correct function, (Then vertex v will be necessary.) or in generating neighbours code fragment.
Now you can implement it basing on wikipedia. You have graph.
Why you shouldn't listen?
Better way is to use Belman Ford Algorithm from other vertex. Notice, that if you know optimal path from A to B, you also know optimal path from B to A. Why? Always you have to pay for last vertex and you don't pay for first, so you can ignore costs of them. Rest is obvious.
Now, if you know that you want to know paths A->B and B->C, you can calculate B->A and B->C using one time BF from node B and reverse path B->A. It's over.
You just have to erase outgoing edges from entry and exit nodes.
However, if you need very fast algorithm, you have to optimize that. But it is for another topic, I think. Also, it looks like no one is interested in hard optimization.
I can quickly add, just that small and easy optimization bases at that, that you can ignore relaxation from correspondingly distant vertices. In array you can calculate distance in easy way, so it's pleasant optimization.
I have not mentioned well know optimization, cause I believe that all of them are in a random course of the web.

Reducing time complexity in maximal minimum-sum 2-partitioning of an array

Let array[N] an array of N non-negative values. We're trying to recursively partition the array in two (2) subarrays, so that we can achieve the maximum "minimum-sum" of each subarray. The solution is described by the following recursion:
We want to calculate opt[0][N-1].
Let c[x][y] denote the sum{array[i]} from x up to y (including).
I have managed to unwind the recursion in the following C++ code snippet, using dynamic programming:
for ( uint16_t K1 = 0; K1 < N; K1 ++ ) {
for ( uint16_t K2 = 0; K2 < N-K1; K2 ++ ) {
const uint16_t x = K2, y = K2 + K1;
opt[x][y] = 0;
for ( uint16_t w = x; w < y; w ++ ) {
uint32_t left = c[x][w] + opt[x][w];
uint32_t right = c[w+1][y] + opt[w+1][y];
/* Choose minimum between left-right */
uint32_t val = MIN( left, right );
/* Best opt[x][y] ? */
if ( val > opt[x][y] ) {
opt[x][y] = val;
}
}
} /* K2 */
} /* K1 */
This technique parses all subarrays, beginning from size 1 and up to size N. The final solution will thus be stored in opt[0][N-1].
For example, if N=6, the matrix will be iterated as follows: (0,0) (1,1) (2,2) (3,3) (4,4) (5,5) (0,1) (1,2) (2,3) (3,4) (4,5) (0,2) (1,3) (2,4) (3,5) (0,3) (1,4) (2,5) (0,4) (1,5) (0,5). The final answer will be in opt[0][5].
I have tested and verified that the above technique works to unwind the recursion. I am trying to further reduce the complexity, as this will run in O(n^3), if I'm correct. Could this be achieved?
edit: I'm also noting the physical meaning of the recursion, as it was asked in the comments. Let N denote N cities across a straight line. We're a landlord who controls these cities; at the end of a year, each city i pays an upkeep of array[i] coins as long as it's under our control.
Our cities are under attack by a superior force and defeat is unavoidable. At the beginning of each year, we erect a wall between two adjacent cities i,i+1, x <= i <= y. During each year, the enemy forces will attack either from the west, thus conquering all cities in [x,i], or will attack from the east, thus conquering all cities in [i+1,y]. The remaining cities will pay us their upkeep at the end of the year. The enemy forces destroy the wall at the end of the year, retreat, and launch a new attack in the following year. The game ends when only 1 city is left standing.
The enemy forces will always attack from the optimal position, in order to reduce our maximum income over time. Our strategy is to choose the optimal position of the wall, so as to maximize our total income at the end of the game.
Here's the final answer to the problem, following the contribution of #NiklasB. . Let w(x,y) denote the optimal partition of an array for the problem opt[x][y]. As follows, x <= w(x,y) < y. We assume that the positions for all subproblems opt[x][y] with a given subarray size d = y-x are known.
Let's now try to find the optimal w positions for all subproblems of size k+1. We can easily prove that w(x,y+1) >= w(x,y); IOW if we add another element to the right, the optimal partition might "move to the right", in order to more evenly balance the two sums; it however cannot "move to the left". In a similar fashion, w(x-1,y) <= w(x,y).
NB: it would be helpful if someone could attempt to mathematically verify the above.
As follows, let wall[x][y] denote the optimal w solution for the subproblem opt[x][y]. Loop for ( uint16_t w = x; w < y; w ++ ) in the original snippet, will be modified as follows:
for ( uint16_t w = wall[x][y-1]; w <= wall[x+1][y]; w ++ ) {
...
if ( val > opt[x][y] ) {
opt[x][y] = val;
wall[x][y] = w;
}
}
A few modifications are needed to deal with corner cases when 0 <= y-x <= 1, but it does the job. It reduces the running time complexity from O(n^3) to O(n^2), since the time to compute the solution for a larger subproblem is amortized O(1), by taking into account the w boundaries. Example: with N = 2500, the recursive algorithm (with memoization) runs in 58 sec. The O(n^2) algorithm runs in only 148 msec.

4 by 3 lock pattern

I came across this problem.
which asks to calculate the number of ways a lock pattern of a specific length can be made in 4x3 grid and follows the rules. there may be some of the points must not be included in the path
A valid pattern has the following properties:
A pattern can be represented using the sequence of points which it's touching for the first time (in the same order of drawing the pattern), a pattern going from (1,1) to (2,2) is not the same as a pattern going from (2,2) to (1,1).
For every two consecutive points A and B in the pattern representation, if the line segment connecting A and B passes through some other points, these points must be in the sequence also and comes before A and B, otherwise the pattern will be invalid. For example a pattern representation which starts with (3,1) then (1,3) is invalid because the segment passes through (2,2) which didn't appear in the pattern representation before (3,1), and the correct representation for this pattern is (3,1) (2,2) (1,3). But the pattern (2,2) (3,2) (3,1) (1,3) is valid because (2,2) appeared before (3,1).
In the pattern representation we don't mention the same point more than once, even if the pattern will touch this point again through another valid segment, and each segment in the pattern must be going from a point to another point which the pattern didn't touch before and it might go through some points which already appeared in the pattern.
The length of a pattern is the sum of the Manhattan distances between every two consecutive points in the pattern representation. The Manhattan distance between two points (X1, Y1) and (X2, Y2) is |X1 - X2| + |Y1 - Y2| (where |X| means the absolute value of X).
A pattern must touch at least two points
my approach was a brute force, loop over the points, start at the point and using recursive decremente the length until reach a length zero then add 1 to the number of combinations.
Is there a way to calculate it in mathematical equation or there is a better algorithm for this ?
UPDATE:
here is what I have done, it gives some wrong answers ! I think the problem is in isOk function !
notAllowed is a global bit mask of the not allowed points.
bool isOk(int i, int j, int di,int dj, ll visited){
int mini = (i<di)?i:di;
int minj = (j<dj)?j:dj;
if(abs(i-di) == 2 && abs(j-dj) == 2 && !getbit(visited, mini+1, minj+1) )
return false;
if(di == i && abs(j - dj) == 2 && !getbit(visited, i,minj+1) )
return false;
if(di == i && abs(j-dj) == 3 && (!getbit(visited, i,1) || !getbit(visited, i,2)) )
return false;
if(dj == j && abs(i - di) == 2 && !getbit(visited, 1,j) )
return false;
return true;
}
int f(int i, int j, ll visited, int l){
if(l > L) return 0;
short& res = dp[i][j][visited][l];
if(res != -1) return res;
res = 0;
if(l == L) return ++res;
for(int di=0 ; di<gN ; ++di){
for(int dj=0 ; dj<gM ; ++dj){
if( getbit(notAllowed, di, dj) || getbit(visited, di, dj) || !isOk(i,j, di,dj, visited) )
continue;
res += f(di, dj, setbit(visited, di, dj), l+dist(i,j , di,dj));
}
}
return res;
}
My answer to another question can be adapted to this problem as well.
Let f(i,j,visited,k) the number of ways to complete a partial pattern, when we are currently at node (i,j), have already visited the vertices in the set visited and have so far walked a path length of k. We can represent visited as a bitmask.
We can compute f(i,j,visited,k) recursively by trying all possible next moves and apply DP to reuse subproblem solutions:
f(i,j, visited, L) = 1
f(i,j, visited, k) = 0 if k > L
f(i,j, visited, k) = sum(possible moves (i', j'): f(i', j', visited UNION {(i',j')}, k + dis((i,j), (i',j')))
Possible moves are those that cross a number of visited vertices and then end in an univisited (and not forbidden) one.
If D is the set of forbidden vertices, the answer to the question is
sum((i,j) not in D: f(i,j, {(i,j)}, L)).
The runtime is something like O(X^2 * Y^2 * 2^(X*Y) * maximum possible length). I guess the maximum possible length is in fact well below 1000.
UPDATE: I implemented this solution and it got accepted. I enumerated the possible moves in the following way: Assume we are at point (i,j) and have already visited the set of vertices visited. Enumerate all distinct coprime pairs (dx,dy) 0 <= dx < X and 0 <= dy < Y. Then find the smallest k with P_k = (i + kdx, j + kdy) still being a valid grid point and P_k not in visited. If P_k is not forbidden, it is a valid move.
The maximum possible path length is 39.
I'm using a DP array of size 3 * 4 * 2^12 * 40 to store the subproblem results.
There are a couple of attributes of the combinations that may be used to optimize the brute force method:
Using mirror images (horizontal, vertical, or both) you can generate 4 combinations for each one found (except horizontal or vertical lines). Maybe you could consider only combinations starting in one quadrant.
You can usually generate additional combinations of the same length by translation (moving a combination).

minimal cost sum

i want to to calculate minimum sum in given two dimensional array
#include<iostream>
#include<limits.h>
using namespace std;
#define R 3
#define C 3
int Min(int x,int y,int z){
if(x<y){
return (x<z)?x:z;
}
else
return (y<z)?y:z;
}
int mincost(int cost[R][C],int m,int n){
int i,j;
int t[R][C];
t[0][0]=cost[0][0];
for(i=1;i<=m;i++)
t[i][0]=t[i-1][0]+cost[i][0];
for(j=1;j<=n;j++)
t[0][j]=t[0][j-1]+cost[0][j];
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
t[i][j]=Min(t[i-1][j-1],t[i-1][j],t[i][j-1]+cost[i][j]);
}
}
return t[m][n];
}
int main(){
int cost[R][C]={{1,2,3},
{4,8,2},
{1,5,3}};
cout<<mincost(cost,2,2)<<endl;
return 0;
}
from starting point (0,0) to some point (m,n) for this array it equals 8,but output shows me 1,why?what is wrong with this code?
algorithm in words
Given a cost matrix cost[][] and a position (m, n) in cost[][], write a function that returns cost of minimum cost path to reach (m, n) from (0, 0). Each cell of the matrix represents a cost to traverse through that cell. Total cost of a path to reach (m, n) is sum of all the costs on that path (including both source and destination). You can only traverse down, right and diagonally lower cells from a given cell, i.e., from a given cell (i, j), cells (i+1, j), (i, j+1) and (i+1, j+1) can be traversed. You may assume that all costs are positive integers.
I see that this is a dynamic programming solution.
you have a typo here:
t[i][j]=Min(t[i-1][j-1],t[i-1][j],t[i][j-1]+cost[i][j]);
it should be:
t[i][j]=Min(t[i-1][j-1],t[i-1][j],t[i][j-1]) + cost[i][j];
basically it worked like t[i][j] = t[i-1][j-1].
Note: A good way to debug these problems is to print the intermediate matrix (here: t).
Given that t[0][0] = cost[0][0] = 1
then
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
t[i][j]=Min(t[i-1][j-1],t[i-1][j],t[i][j-1]+cost[i][j]);
}
for i=1, j=1
t[1][1] = Min(t[0][0], t[0][1], t[1][0]+cost[1][1]) = Min(1, ...) = 1
for i=2 j=2
t[2][2] = Min(t[1][1], t[1][2], t[2][1]+cost[2][2]) = Min(1, ...) = 1
Min(t[i-1][j-1],t[i-1][j],t[i][j-1]+cost[i][j])
should probably be
Min(t[i-1][j-1],t[i-1][j],t[i][j-1]) +cost[i][j]
Just guessing, it's hard to read your intent, but looks like a pathfinding algorithm. Your code wasn't adding the cost properly to diagonal or horizontal movement, and since the cost of the beginning was one, that was also your result. This should return a cost of eleven for your sample.