Given a rectangular grid of size N × M, namely, there are cells (x, y) for 1 ≤ x ≤ N, 1 ≤ y ≤ M.
Two cells are adjacent if they share a side. More formally, two cells (x1, y1), (x2, y2) are adjacent if |x1 − x2| + |y1 − y2| = 1. Between two adjacent cells there can be a wall. Two cells a and b are connected if there is a way between them (in other words there is a sequence of cells c[1], c[2], ..., c[k] such that c[1] = a, c[k] = b, and for each 1 ≤ i < k, c[i] and c[i+1] are adjacent cells without wall between them).
Now we are given Q queries, each of them is of following four types.
1 x y - Build the wall between cells (x, y) and (x, y+1). If there is already exist a wall between them, this query is ignored.
2 x y - Build the wall between cells (x, y) and (x+1, y). If there is already exist a wall between them, this query is ignored.
3 x1 y1 x2 y2 - Check if cells (x1, y1) and (x2, y2) are connected. Answer to this query is a YES or NO
4 - We need to tell the size of the largest connected component. A connected component is a set of sells wherein each two cells are connected. The size of a connected component is a number of the cells in it.
Note : We can assume that there are no walls on the grid before the queries.
Now given N , M and Q queries we need to tell answer for query of type 3 and 4.
My Approach : I am currently thinking to do it by making a graph and then doing dfs sort of thing for each query. Can this approach be made efficient or is there some other better approach to solve this problem ?
The size of grid is 1000 X 1000 at max. And queries can be up to 10^6
Example : Let N=3 and M=4 and at start we are asked query of type 3 that is (1,1) connected to (3,4) then answer is YES as earlier grid is like this :
http://postimg.org/image/5qoug2dov/
Now suppose we have queries of type 1 and 2 and grid become something like this :
http://postimg.org/image/tm14jtg9h/
Now the answer for same query 3 is NO
Assuming that you can answer queries offline, then working on them in reverse order turns this into an incremental connectivity problem that is perfect for a disjoint-set data structure whose root nodes are augmented with the total number of nodes in the set.
Related
I'm solving a problem and I reduced it to the following one:
Given n points (x1, y1), ..., (xn, yn) (0 <= xi, yi), and two integers A and B (0 <= A, B) I need to find a subset of those points such that:
1) The sum of the x values is at most A (SUM(x) <= A).
2) The sum of the y values is at least B (SUM(y) >= B).
I'm struggling with this problem and I cannot find a solution other than combining. I would appreciate some ideas.
UPD: xi and A are rationals (represented as floats/double). yi and B are integers.
Depending on the distribution and the space available, we could create a "merge sort" segment tree, where the segments divide the X range and the tree array-nodes are sorted by y values. Then test partitions of A such that we can choose multiple xs maxed by the right-bound of each part, choosing the top y values in O(log n) from the segment tree.
I'd like to take a grid of 0's and 1's and arrive at all rectangles present in the grid, which share a common corner.
Similar to the Maximal Rectangle problem -
Link 1
Link 2
But instead of finding a single rectangle with the maximum area, I'd like to find all rectangles that share a common corner. IE if I specify coordinates (10,10) I'd like all possible rectangles that have a bottom left corner of 10,10.
Could someone help explain how I can adapt the implementation of the algorithm I linked to do what I described?
I am not sure about how to adapt the given algorithm for this problem, but I have a good way to solve this problem.
Say, we are given the bottom-left corner for the rectangles at (x1, y1). We keep a count of the number of rectangles(with value 1 and sharing the bottom-left corner) num and a horizontal value till which rectangles can be found at this value of y hval. Now, we traverse horizontally until hval or if we find a 0 in the way, since no rectangles can be made beyond this point. Now, we make this x the new hval. We move to the next row and do the same each time counting the number of rectangles we have passed.
The solution is O(n2). Since we used atmost 2*num steps the complexity of solution is also bounded by θ(num).
This python code sample can provide a better understanding:
num = 0
hval = len(board)
i = 1
x1=1
y1=1
x2 = x1
while (y1 < len(board) and i > 0):
i = 0
while (board[y1][x2] == 1 and x2 < hval):
num += 1
x2 += 1
i += 1
else:
hval = x2
y1 += 1
x2 = x1
print(num)
You don't want or need my linked answer for this. An easy way to do this is to first calculate the "integral image" I[][] of the input matrix M[][] -- that is, a matrix I[][] whose (x, y) entry is the sum of all entries below and to the left of (x, y) in the input matrix. This lets you easily compute the number of 1s in any given rectangle (x1, y1, x2, y2) in constant time using I[x2][y2] - I[x1-1][y2] - I[x2][y1-1] + I[x1-1][y1-1], if (x1, y1) is the bottom-left corner and (x2, y2) is the top-right corner. I[][] can be computed in a one-time O(n^2) preprocessing step.
For a given bottom-left corner (x1, y1), you can then simply loop through all widths w and heights h in increasing order using a pair of nested loops, testing whether the number of 1s in the rectangle (x1, y1, x1+w, y2+h) is the number of 1s that should be there in an all-1 rectangle -- i.e., (b+1)*(h+1). As soon as this fails to hold, exit that loop early (since clearly if some rectangle is not an all-1 rectangle, then no rectangle that contains it can be either).
This algorithm is of course O(n^2)-time for an n*n rectangle, but there is no avoiding this worst case (consider an input matrix in which every entry is 1).
Input: S = {p1, . . . , pn}, n points on 2D plane each point is given by its x and y-coordinate.
For simplicity, we assume:
The origin (0, 0) is NOT in S.
Any line L passing through (0, 0) contains at most one point in S.
No three points in S lie on the same line.
If we pick any three points from S, we can form a triangle. So the total number of triangles that can be formed this way is Θ(n^3).
Some of these triangles contain (0, 0), some do not.
Problem: Calculate the number of triangles that contain (0, 0).
You may assume we have an O(1) time function Test(pi, pj , pk) that, given three points pi, pj , pk in S, returns 1, if the triangle formed by {pi, pj , pk} contains (0, 0), and returns 0 otherwise. It’s trivial to solve the problem in Θ(n^3) time (just enumerate and test all triangles).
Describe an algorithm for solving this problem with O(n log n) run time.
My analysis of the above problem leads to the following conclusion
There are 4 coordinates ( + ,+ ) , ( + ,- ) , ( -, - ), ( -, + ) { x and y coordinate > 0 or not }.
Let
s1 = coordinate x < 0 and y > 0
s2 = x > 0 , y > 0
s3 = x < 0 , y < 0
s4 = x > 0 , y < 0
Now we need to do the testing of points in between sets of the following combinations only
S1 S2 S3
S1 S1 S4
S2 S2 S3
S3 S3 S2
S1 S4 S4
S1 S3 S4
S1 S2 S4
S2 S3 S4
I now need to test the points in the above combination of sets only ( e.g. one point from s1 , one point from s2 and one point from s3 < first combinaton > ) and see the points contain (0,0) by calling Test function ( which is assumed as constant time function here) .
Can someone guide me on this ?
Image added below for clarification on why only some subsets (s1,s2 , s4 ) can contain (0,0) and some ( s1,s1,s3) cannot.
I'm guessing we're in the same class (based on the strange wording of the question), so now that the due date is past, I feel alright giving out my solution. I managed to find the n log n algorithm, which, as the question stated, is more a matter of cleverly transforming the problem, and less of a Dynamic Programming / DaC solution.
Note: This is not an exhaustive proof, I leave that to you.
First, some visual observations. Take some triangle that obviously contains the origin.
Then, convert the points to vectors.
Convince yourself that any selection of three points, one from each vector, describes a triangle that also contains the origin.
It also follows that, if you perform the above steps on a triangle that doesn't enclose the origin, any combination of points along those vectors will also not contain the origin.
The main point to get from this is, the magnitude of the vector does not matter, only the direction. Additionally, a hint to the question says that "any line crossing (0,0) only contains one point in S", from which we can extrapolate that the direction of each vector is unique.
So, if only the angle matters, it would follow that there is some logic that determines what range of points, given two points, could possibly form a triangle that encloses the origin. For simplicity, we'll assume we've taken all the points in S and converted them to vectors, then normalized them, effectively making all points lie on the unit circle.
So, take two points along this circle.
Then, draw a line from each point through the origin and to the opposite side of the circle.
It follows that, given the two points, any point that lies along the red arc can form a triangle.
So our algorithm should do the following:
Take each point in S. Make a secondary array A, and for each point, add the angle along the unit circle (atan2(x,y)) to A (0 ≤ Ai ≤ 2π). Let's assume this is O(n)
Sort A by increasing. O(n log n), assuming we use Merge Sort.
Count the number of triangles possible for each pair (Ai,Aj). This means that we count the number of Ai + π ≤ Ak ≤ Aj + π. Since the array is sorted, we can use a Binary Search to find the indices of Ai + π and Aj + π, which is O(2 log n) = O(log n)
However, we run into a problem, there are n^2 points, and if we have to do an O(log n) search for each, we have O(n^2 log n). So, we need to make one more observation.
Given some Ai < Aj, we'll say Tij describes the number of triangles possible, as calculated by the above method. Then, given a third Ak > Aj, we know that Tij ≤ Tik, as the number of points between Ai + π and Ak + π must be at least as many as there are betwen Ai + π and Aj + π. In fact, it is exactly the count between Ai + π and Aj + π, plus the count between Aj + π and Ak + π. Since we already know the count between Ai + π and Aj + π, we don't need to recalculate it - we only need to calculate the number between Aj + π and Ak + π, then add the previous count. It follows that:
A(n) = count(A(n),A(n-1)) + count(A(n-1),A(n-2)) + ... + count(A(1),A(0))
And this means we don't need to check all n^2 pairs, we only need to check consecutive pairs - so, only n-1.
So, all the above can give us the following psuedocode solution.
int triangleCount(point P[],int n)
int A[n], C[n], totalCount = 0;
for(i=0...n)
A[i] = atan2(P[i].x,P[i].y);
mergeSort(A);
int midPoint = binarySearch(A,π);
for(i=0...midPoint-1)
int left = A[i] + π, right = A[i+1] + π;
C[i] = binarySearch(a,right) - binarySearch(a,left);
for(j=0...i)
totalCount += C[j]
return totalCount;
It seems that in the worst case there are Θ(n3) triangles containing the origin, and since you need them all, the answer is no, there is no better algorithm.
For a worst case consider a regular polygon of an odd degree n, centered at the origin.
Here is an outline of the calculations. A chord connecting two vertices which are k < n/2 vertices apart is a base for Θ(k) triangles. Fix a vertex; its contribution is a sum over all chords coming from it, yielding Θ(n2), and a total (a contribution of all n vertices) is Θ(n3) (each triangle is counted 3 times, which doesn't affect the asymptotic).
http://www.cs.uiuc.edu/~jeffe/teaching/algorithms/notes/05-dynprog.pdf
I was doing these questions for practice where I came across one that stumped me.
7.(a) Suppose we are given a set L of n line segments in the plane, where each segment has one endpoint on the line y = 0 and one endpoint
on the line y = 1, and all 2n endpoints are distinct. Describe and
analyze an algorithm to compute the largest subset of L in which no
pair of segments intersects.
(b) Suppose we are given a set L of n line segments in the plane,
where the endpoints of each segment lie on the unit circle x 2 + y 2 =
1, and all 2n endpoints are distinct. Describe and analyze an
algorithm to compute the largest subset of L in which no pair of
segments intersects.
I figured out how to do 7a, (the question is a disguised problem to find the largest subset of increasing numbers), in O(n log n) time. Im almost close to giving up on 7b, as I cant figure out a way to do it.
However, is there a way to convert 7b's premise to something more like 7a's? I feel like that's the right way of approaching the problem, and any help in figuring this out would be much appreciated.
I couldn't come up with an O(n*log(n)) algorithm, but here is an O(n2) one.
The idea is that we build a directed graph with vertices representing segments from the given set and edges representing the "lies to the right of" relation.
Let L be the list of segments: {(a1, b1), (a2, b2), ..., (an, bn)}, where ak and bk are k-th segment's endpoints.
Let L' be the list of segments: {(a1, b1), (b1, a1), (a2, b2), (b2, a2), ..., (an, bn), (bn, an)}.
Let the vertices of the graph have indices from 1 to 2*n, each index k representing the segment L'[k], i.e. (ak/2, bk/2) if k is odd, and (bk/2, ak/2) if k is even.
A segment (a1, b1) is said to lie to the right of a segment (a2, b2) when the points a1, a2, b2, b1 are placed in a clockwise order on the unit circle.
Note that 1) If one segment lies to the right of another, they don't intersect; 2) If two segments from L don't intersect, two of the four corresponding segments from L' necessarily lie one to the right of another; 3) Any set of non-intersecting segments from L is defined by a series of segments of L', each lying to the right of the previous one.
Outline of the algorithm:
for every k1 from 1 to 2*n:
for every k2 from 1 to 2*n:
if (L'[k1].a, L'[k1].b) lies to the right of (L'[k2].a, L'[k2].b):
add a directed edge (k1, k2) to the graph
Find the longest path in the graph: (k1, k2, ..., km).
The answer to the problem is: (k1/2, k2/2, ..., km/2).
Here is an O(n2) algorithm.
We have 2n endpoints on the circle. Pick any point and start labeling the points in increasing order starting from 1 in clockwise direction. So, we have points labeled from 1 to 2n. Thus, any line segment l can be represented as (i,j) where i and j are endpoints of l and 1≤i<j≤2n.
Let Li,j be a subset of L such that l=(a,b) ∈ Li,j if i ≤ a < b ≤ j. Also, define D[i,j] for 1 ≤ i ≤ j ≤ 2n as the maximum number of non-intersecting lines in Li,j. We need to find D[1,2n].
We use dynamic programming here. Initialize D[i,i] as 0 and D[i,i+1] as 1 if (i,i+1) is a line segment, otherwise set it as 0. We can build D using the following:
if (i,j) is a line segment :
D[i,j] = D[i+1,j-1]+1
else if (i,k) is a line segment and i<k<j :
D[i,j] = max(D[i,j] , D[i+1,k-1]+D[k+1,j]+1)
else if (k,j) is a line segment and i<k<j :
D[i,j] = max(D[i,j] , D[i,k-1]+D[k+1,j-1]+1)
else :
D[i,j] = max(D[i,j] , D[i+1,j-1])
Since D occupies O(n2) space and we compute each cell of D in constant time the time complexity of the algorithm is O(n2).
Reference:
http://www.cs.toronto.edu/~robere/csc373h/files/A2-sol.pdf
Look under the heading Line Intersections (Redux)
Create two lists. The first list has the ordering created by sweeping counter-clockwise around the circle starting at (1,0). The first endpoint of a segment you hit is marked. The second list is ordered the same, but go clockwise around the circle. In this manner, you now have two lists where the segment endpoints show an ordering for intersection. For example, if the first point in the first list doesn't have its corresponding endpoint first in the second list, then it will intersect with all of the segments which appear before it in the second list. (You need to be careful here in that both points for a line can be before the end of your segment. A simple check eliminates this.) You can then just run the list. The total complexity of this approach seems to be O(n log n) for each list creation and O(n) for running the list.
I have to design an algorithm with running time O(nlogn) for the following problem:
Given a set P of n points, determine a value A > 0 such that the shear transformation (x,y) -> (x+Ay,y) does not change the order (in x direction) of points with unequal x-coordinates.
I am having a lot of difficulty even figuring out where to begin.
Any help with this would be greatly appreciated!
Thank you!
I think y = 0.
When x = 0, A > 0
(x,y) -> (x+Ay,y)
-> (0+(A*0),0) = (0,0)
When x = 1, A > 0
(x,y) -> (x+Ay,y)
-> (1+(A*0),0) = (1,0)
with unequal x-coordinates, (2,0), (3,0), (4,0)...
So, I think that the begin point may be (0,0), x=0.
Suppose all x,y coordinates are positive numbers. (Without loss of generality, one can add offsets.) In time O(n log n), sort a list L of the points, primarily in ascending order by x coordinates and secondarily in ascending order by y coordinates. In time O(n), process point pairs (in L order) as follows. Let p, q be any two consecutive points in L, and let px, qx, py, qy denote their x and y coordinate values. From there you just need to consider several cases and it should be obvious what to do: If px=qx, do nothing. Else, if py<=qy, do nothing. Else (px>qx, py>qy) require that px + A*py < qx + A*qy, i.e. (px-qx)/(py-qy) > A.
So: Go through L in order, and find the largest A' that is satisfied for all point pairs where px>qx and py>qy. Then choose a value of A that's a little less than A', for example, A'/2. (Or, if the object of the problem is to find the largest such A, just report the A' value.)
Ok, here's a rough stab at a method.
Sort the list of points by x order. (This gives the O(nlogn)--all the following steps are O(n).)
Generate a new list of dx_i = x_(i+1) - x_i, the differences between the x coordinates. As the x_i are ordered, all of these dx_i >= 0.
Now for some A, the transformed dx_i(A) will be x_(i+1) -x_i + A * ( y_(i+1) - y_i). There will be an order change if this is negative or zero (x_(i+1)(A) < x_i(A).
So for each dx_i, find the value of A that would make dx_i(A) zero, namely
A_i = - (x_(i+1) - x_i)/(y_(i+1) - y_i). You now have a list of coefficients that would 'cause' an order swap between a consecutive (in x-order) pair of points. Watch for division by zero, but that's the case where two points have the same y, these points will not change order. Some of the A_i will be negative, discard these as you want A>0. (Negative A_i will also induce an order swap, so the A>0 requirement is a little arbitrary.)
Find the smallest A_i > 0 in the list. So any A with 0 < A < A_i(min) will be a shear that does not change the order of your points. Pick A_i(min) as that will bring two points to the same x, but not past each other.