4

You are given a grid of 0's and 1's and it's dimension 1 ≤ N,M ≤ 2500 and a number 0 ≤ K ≤ 6. The task is to count the number of rectangles in the grid that have exactly K ones inside it.

It has to be quicker that O(N^2*M), something like O(NMlog(N+M)) will work. My best aproach was a dp with complexity O(N^2*M), but this is to slow, I've been told that the answer is divide and conquer but I can't get it. Any idea?

Dru01
  • 95
  • 7
  • Is there a constraint on the memory you can use? For example can you allocate another buffer of max 2500×2500? – RocketNuts Mar 19 '19 at 09:30
  • O(N^2*log(N)) doesn't make sense here when the grid is NxM. Do you mean O(n^2*log(n)) where n is NxM (the size of the input)? – Dave Mar 19 '19 at 13:55
  • @Dave my bad, I was taking N for the maximum value between N and M. – Dru01 Mar 19 '19 at 15:27

1 Answers1

2

One way to get the log factor is to divide horizontally, add the number of rectangles with K 1s above the dividing line, the number of rectangles with K 1s below the dividing line (computed recursively), and for each horizontal width, (there are O(|columns|^2) of them) the number of rectangles that extend some part above and some part below the divided line with the same fixed width. We compute the last one by splitting into two-part partitions of K (maxed at 7 since K ≤ 6 and we may want one part zero). We can binary search on a fixed width and bottom or top line, up or down, on matrix prefix sums, which we can precalculate in O(M * N) and retrieve in O(1).

f(vertical_range) =
  f(top_part) +
  f(bottom_part) +
  NumTopRecs(w, i) * NumBottomRecs(w, k - i)
    where i <- [0...k],
          w <- all O(M^2) widths

The trick is that in each recursive call, we rotate the half that's passed to f such that the horizontal divider line becomes vertical, which means we've cut the M for our call (from which we draw O(M^2) widths) in 2.

גלעד ברקן
  • 23,602
  • 3
  • 25
  • 61
  • Thank you so much, the computing part was what I can figure it out but now a I can see it. – Dru01 Mar 19 '19 at 23:57
  • Great answer! Starting with T(N, M) = T(M, N/2) + T(M, N/2) + M^2*log(N), unrolling 2 levels of recursion gives T(N, M) = 4T(N/2, M/2) + N^2/2*log(M) + M^2*log(N). If we substitute M=AN, treating the aspect ratio A as a constant, then we can write T() as a function of just a single parameter, N: T(N) = 4T(N/2) + (A^2 + 1/2)N^2*log(N) + log(A)/2*N^2 = 4T(N/2) + O(N^2*log(N)). This gives T(N) = O(N^2*log(N)^2) by the Master Theorem. :) – j_random_hacker Mar 21 '19 at 10:43