Блог пользователя Enigma20

Автор Enigma20, история, 3 года назад, По-английски

I recently participated in Google's Online Coding Challenge. Following is one of the 2 questions given to me. I couldn't solve it during the contest. After the contest, I looked up the internet for the same but to no avail. Question goes as follows,

Problem:

You are given a $$$N*M$$$ matrix where each cell has a positive number, $$$A_{ij}$$$, written on it. You need to start from first column and end at last column such that the cost of the path taken is minimum possible. We define cost of the path as difference between maximum and minimum value among all values lying on the chosen path.

In one move you can go to any row of $$$(j+1)^{th}$$$ column from $$$j^{th}$$$ column. You can start from any row of first column and end up on any row of last column. Find the minimum possible cost.

Constraints:

$$$1\leq N,M\leq 500$$$
$$$1\leq A_{ij}\leq 10^9$$$

I was thinking some modification of some standard DP would do but couldn't come up with one.
Any help will be appreciated. Thanks!

  • Проголосовать: нравится
  • +27
  • Проголосовать: не нравится

»
3 года назад, # |
Rev. 2   Проголосовать: нравится +22 Проголосовать: не нравится

How are you guys giving these rounds? I didn't even know they exist :(

»
3 года назад, # |
Rev. 3   Проголосовать: нравится +45 Проголосовать: не нравится

Basically the same as this problem (if I remember correctly): https://codeforces.me/problemset/problem/1413/C

For each cell $$$A_{ij}$$$, generate a pair $$$(A_{ij}, j)$$$. Now sort these pairs in ascending order. Let's denote $$$f_i$$$ as the first value of the $$$i$$$th pair, and $$$s_i$$$ as the second value of the $$$i$$$th pair (when sorted).

(edit: why do I need to do this to get a new paragraph :/) The problem is equivalent to finding the segment $$$[l, r]$$$

with minimum $$$f_r - f_l$$$ such that the set of values $$$s_l, s_{l + 1}, ..., s_r$$$ contain every single element from $$$1$$$ to $$$M$$$. This can be solved via 2 pointers in $$$O(NM)$$$.
  • »
    »
    3 года назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Thanks a lot mate! Got it.

  • »
    »
    3 года назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Checking if sl,sl+1,...,sr contains every single element from 1 to M, would require another O(M) time which would make the complexity O(N*M^2). Is there any other way to solve this?

    • »
      »
      »
      3 года назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      It wouldn't. You can maintain the count of each element, and the count of the number of distinct elements, with additions and removals in constant time.

»
3 года назад, # |
  Проголосовать: нравится +44 Проголосовать: не нравится

Make pairs as {element, column number in which this element exist}, and then sort them.

The problem reduces to sliding window where you have to maintain window with count of each column number >= 1.

Whenever you find such window update ans = min(ans, difference of extreme elements of window).

»
3 года назад, # |
  Проголосовать: нравится +2 Проголосовать: не нравится

sort pair<element,col> and iterate using two pointers to find best possible segment containing all columns.

»
3 года назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится

What was the other question that you got in the round, can you share, please?

  • »
    »
    3 года назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    It was problem 1 in this blog
    https://codeforces.me/blog/entry/92729

    • »
      »
      »
      3 года назад, # ^ |
        Проголосовать: нравится +4 Проголосовать: не нравится

      Oh, you got a comparatively tough set.

      • »
        »
        »
        »
        3 года назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Yeah, but I must admit I was a little lucky too. I managed to solve the first one using Trie which I later came to know was not optimal. It would have given TLE if tests were strong. But as usual they don't seem very difficult knowing the answer :(

        • »
          »
          »
          »
          »
          3 года назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          Can you share your trie implementation for that problem? I found it difficult to implement as there are two possible choices if we encounter a 0-bit.

          • »
            »
            »
            »
            »
            »
            3 года назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится

            Actually, that's what makes it non-optimal. If current bit is 1, I am simply checking recursively towards 0 bit. In case where current bit is 0, I recursively checked towards both 1 and 0 bit and returned true if anyone of the two recursive calls returned true.

»
3 года назад, # |
  Проголосовать: нравится +6 Проголосовать: не нравится

I think we can iterate on the minimum element on our path, let our matrix at any time contain only those values which are greater than the fixed element, than we can find the element just greater than the fixed element in each column easily, this leads to O(N*M*log(N*M)) solution.

  • »
    »
    3 года назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Sorry, didn't understand completely. Are you implying that we should binary search over the minimum element in our path? What exactly is the 'fixed element' here?

    • »
      »
      »
      3 года назад, # ^ |
        Проголосовать: нравится +8 Проголосовать: не нравится

      Sort all the elements in each column consider each column as stacks now consider the min element of top of each stack (the fixed element) and the max element on top of each stack, now update the answer using this max — min, then pop this min element. hence we end up with solution of complexity O(N*M*log(M)) where we checked for each min element that is possible to be on our path(which I was telling to iterate on). Hope you get the gist from above implementation.

»
3 года назад, # |
Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

I was thinking in following manner -
So, since the order does not matter we can sort up individual columns.
Now, if we fix up a value as maximum then if we can get what minimum difference with this we can get, then we can do this. For this, from other columns we should take least of just less or equal elements than fixed value
So, to process this, we can take a max priority_queue and fill up with greatest element(as tuple of element, row, column) of each column, also store the present minimum of all things present in priority_queue.
Now, we can take out the maximum value and take the current minimum, update the answer, take out the maximum and then store the next maximum of that column in priority_queue, update the current minimum if necessary.
Instead of priority_queue, we can also use set to get max and min, but that has somewhat higher complexity.

»
3 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

which platform was the test conducted on?

»
3 года назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

was this contest for full time or intern hiring?

»
3 года назад, # |
Rev. 2   Проголосовать: нравится +3 Проголосовать: не нравится

I think there is very simple solution for this. Sort all the elements of the matrix in an array of size $$$NM$$$ (make sure elements holds the information about its column). Now our answer will be $$$last_{element}-first_{element}$$$ of some least possible size sub-array which contains all the columns from $$$1-M$$$. Now this can be done using sliding window technique. Due to sorting complexity is $$$O(NMlog(NM))$$$