Cutting Boards
Difficulty: Hard

Alice gives Bob a board composed of $1 \times 1$ wooden squares and asks him to find the minimum cost of breaking the board back down into its individual squares. To break the board down, Bob must make cuts along its horizontal and vertical lines. 

To reduce the board to squares, Bob makes horizontal and vertical cuts across the entire board.  Each cut has a given cost, $cost\_y[i]$ or $cost\_x[j]$ for each cut along a row or column across one board, so the cost of a cut must be multiplied by the number of segments it crosses.  The cost of cutting the whole board down into $1 \times 1$ squares is the sum of the costs of each successive cut.   

Can you help Bob find the minimum cost?  The number may be large, so print the value modulo $10^9+7$.

For example, you start with a $2\times 2$ board.  There are two cuts to be made at a cost of $cost\_y[1]=3$ for the horizontal and $cost\_x[1]=1$ for the vertical.  Your first cut is across $1$ piece, the whole board.  You choose to make the horizontal cut between rows $1$ and $2$ for a cost of $1\times 3=3$.  The second cuts are vertical through the two smaller boards created in step $1$ between columns $1$ and $2$.  Their cost is $2\times 1=2$.  The total cost is $3 + 2=5$ and $5\%(10^9+7)=5$.

**Function Description**  

Complete the *boardCutting* function in the editor below.  It should return an integer.  

boardCutting has the following parameter(s):  

- *cost_x*: an array of integers, the costs of vertical cuts  
- *cost_y*: an array of integers, the costs of horizontal cuts  

Input Format:
The first line contains an integer $q$, the number of queries.

The following $q$ sets of lines are as follows:

- The first line has two positive space-separated integers $m$ and $n$, the number of rows and columns in the board. 	
- The second line contains $m-1$ space-separated integers cost_y[i], the cost of a  horizontal cut between rows $[i]$ and $[i+1]$ of one board.
- The third line contains $n-1$ space-separated integers cost_x[j], the cost of a vertical cut between columns $[j]$ and $[j+1]$ of one board.


Output Format:
For each of the $q$ queries, find the minimum cost ($minCost$) of cutting the board into $1 \times 1$ squares and print the value of $minCost \text{ % } (10^9+7)$.

**Sample Input 0**
	
    1
	2 2
	2
	1
    
**Sample Output 0**

	4
    
**Explanation 0** 		
We have a $2 \times 2$ board, with cut costs $cost\_y[1] = 2$ and $cost\_x[1] = 1$. Our first cut is horizontal between $y[1]$ and $y[2]$, because that is the line with the highest cost ($2$). Our second cut is vertical, at $x[1]$. Our first cut has a $totalCost$ of $2$ because we are making a cut with cost $cost\_y[1]=2$ across $1$ segment, the uncut board. The second cut also has a $totalCost$ of $2$ but we are making a cut of cost $cost\_x[1]=1$ across $2$ segments. Our answer is $minCost = ( (2 \times 1) + (1 \times 2) ) \ \% \ (10^9+7) = 4$.
    
**Sample Input 1**

	1
    6 4
    2 1 3 1 4
    4 1 2
    
**Sample Output 1**  
	
    42

**Explanation 1** 		
Our sequence of cuts is: $y[5]$, $x[1]$, $y[3]$, $y[1]$, $x[3]$, $y[2]$, $y[4]$ and $x[2]$. 		
*Cut 1:* Horizontal with cost $cost\_y[5] = 4$ across $1$ segment. $totalCost = 4 \times 1 = 4$.		
*Cut 2:* Vertical with cost $cost\_x[1] = 4$ across $2$ segments. $totalCost =	4 \times 2 = 8$.		
*Cut 3:* Horizontal with cost $cost\_y[3] = 3$ across $2$ segments. $totalCost = 3 \times 2 = 6$.		
*Cut 4:* Horizontal with cost $cost\_y[1] = 2$ across $2$ segments. $totalCost = 2 \times 2 = 4$.		
*Cut 5:* Vertical with cost $cost\_x[3] = 2$ across $4$ segments. $totalCost =	2 \times 4 = 8$.		
*Cut 6:* Horizontal with cost $cost\_y[2] = 1$ across $3$ segments. $totalCost = 1 \times 3 = 3$.		
*Cut 7:* Horizontal with cost $cost\_y[4] = 1$ across $3$ segments. $totalCost = 1 \times 3 = 3$.		
*Cut 8:* Vertical with cost $cost\_x[2] = 1$ across $6$ segments. $totalCost =	1 \times 6 = 6$.		

$totalCost =4 + 8 + 6 + 4 + 8 + 3 + 3 + 6 = 42$. We then print the value of $42 \ \% \ (10^9 + 7)$.		



Sample Input:

Sample Output:

Python 3 starter code:
#
# Complete the 'boardCutting' function below.
#
# The function is expected to return an INTEGER.
# The function accepts following parameters:
#  1. INTEGER_ARRAY cost_y
#  2. INTEGER_ARRAY cost_x
#

def boardCutting(cost_y, cost_x):
    # Write your code here



Editorial: Cutting Boards - 2020 Hack February Editorial
<style id="MathJax_SVG_styles">.MathJax_SVG_Display {text-align: center; margin: 1em 0em; position: relative; display: block!important; text-indent: 0; max-width: none; max-height: none; min-width: 0; min-height: 0; width: 100%}
.MathJax_SVG .MJX-monospace {font-family: monospace}
.MathJax_SVG .MJX-sans-serif {font-family: sans-serif}
.MathJax_SVG {display: inline; font-style: normal; font-weight: normal; line-height: normal; font-size: 100%; font-size-adjust: none; text-indent: 0; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0; min-height: 0; border: 0; padding: 0; margin: 0}
.MathJax_SVG * {transition: none; -webkit-transition: none; -moz-transition: none; -ms-transition: none; -o-transition: none}
.mjx-svg-href {fill: blue; stroke: blue}
.MathJax_SVG_LineBox {display: table!important}
.MathJax_SVG_LineBox span {display: table-cell!important; width: 10000em!important; min-width: 0; max-width: none; padding: 0; border: 0; margin: 0}
</style><svg style="display: none;"><defs id="MathJax_SVG_glyphs"></defs></svg><p><a href="https://www.hackerrank.com/contests/feb14/challenges/board-cutting">Cutting Boards</a></p>

<p><strong>Difficulty</strong> : Easy-Medium  </p>

<p><strong>Required Knowledge</strong> : Greedy Algorithm  </p>

<p><strong>Approach</strong> </p>

<p>The board should be broken in square wooden pieces, so that means we have to cut the board along every horizontal and verticle line.The order in which we make the cuts is important here.For minimum cost, sort the lines according to cost in decreasing order.  </p>

<p>Let there be a 5x5 board and the cost along horizontal lines be y1,y2,y3,y4,y5 and along verticle lines be x1,x2,x3,x4,x5</p>

<p>Sort the lines according to cost in decreasing order.Let the lines be y4,x3,y5,x2,x1,y1,x4,y2,y3,x5 in decreasing order of cost.</p>

<pre><code>V = number of vertical cuts
H = number of horizontal cuts
</code></pre>

<p>Initially both V and H be zero
minimum_cost=0
Now traverse the lines in sorted order
    if the line is horizontal
              minimum_cost+=(cost of cut along that particular line)<em>(V+1)
          H++
    if the line is verticle
             minimum_cost+=(cost of cut along that particular line)</em>(H+1)
         V++</p>

<p><strong>Setter's Solution</strong></p>

<pre><code>#include&lt;cstdio&gt;
#include&lt;iostream&gt;
#include&lt;algorithm&gt;
using namespace std;
struct arr{
    long long int val;
    int horv;
};
typedef struct arr arr;
int compare(arr c , arr d){
    if(c.val &gt; d.val){
        return 1;
    }
    return 0;
}
arr a[2000020];
int main(){
    int tc;
    scanf("%d",&amp;tc);
    while(tc--){
        int n,m;
        scanf("%d %d",&amp;m,&amp;n);
        int i;
        int j=0;
        for(i=1;i&lt;m;i++){
            scanf("%lld",&amp;a[j].val);
            a[j].horv=1;    // its a horizontal line
            j++;
        }
        for(i=1;i&lt;n;i++){
            scanf("%lld",&amp;a[j].val);
            a[j].horv=0;  // verticle line
            j++;
        }
        sort(a,a+j,compare);
        int v=0;
        int h=0;
        long long int cost=0;
        for(i=0;i&lt;j;i++){
            if(a[i].horv==1){  // making cut along horizontal line
                cost=(cost+(a[i].val*(v+1))%1000000007)%1000000007;
                h++;
            }
            else if(a[i].horv==0){  // making cut along verticle line
                cost=(cost+(a[i].val*(h+1))%1000000007)%1000000007;
                v++;
            }
        }
        printf("%lld\n",cost);
    }
    return 0;
}
</code></pre>

<p><strong>Tester's Solution</strong></p>

<pre><code>-- {{{
module Main where
---------------------Import-------------------------
import Data.List
import qualified Data.Map as Map
import qualified Data.Set as Set
import Data.Char
import Data.Int                                     -- Int32, Int64
import System.IO
import Data.Ratio                                   -- x = 5%6
import Data.Bits                                    -- (.&amp;.), (.|.), shiftL...
import Text.Printf                                  -- printf "%0.6f" (1.0)
import Control.Monad
import qualified Data.ByteString.Lazy.Char8 as BS
import qualified Data.Vector as V
import System.Directory
import System.FilePath
-- }}}

main :: IO ()
main = BS.getContents &gt;&gt;= mapM_ print. validate. map readIntegerArray. BS.lines

p :: Integer
p = 10^9+7

validate :: [[Integer]] -&gt; [Integer]
validate ([t]: arr)
  | 3 * fromIntegral t /= length arr = error "t /= 3*length arr"
  | t &lt; 0 || t &gt; 20                  = error "t is out of bound"
  | otherwise                        = parse arr

parse :: [[Integer]] -&gt; [Integer]
parse [] = []
parse ([n, m]: a: b: left)
  | n &lt; 0 || n &gt; 10^6               = error "n is out of range"
  | m &lt; 0 || m &gt; 10^6               = error "m is out of range"
  | fromIntegral n - 1 /= length a  = error "n - 1 /= length a"
  | fromIntegral m - 1 /= length b  = error "m - 1 /= length b"
  | any (\x -&gt; x &lt; 0 || x &gt; 10^9) a = error "element of a is out of bound"
  | any (\x -&gt; x &lt; 0 || x &gt; 10^9) b = error "element of a is out of bound"
  | otherwise = (solve a b): parse left

solve :: [Integer] -&gt; [Integer] -&gt; Integer
solve aa bb = solve1 1 (reverse. sort`$ aa) 1 (reverse. sort $`bb)
  where
    solve1 :: Integer -&gt; [Integer] -&gt; Integer -&gt; [Integer] -&gt; Integer
    solve1    _          []           _          []         = 0
    solve1    aCut       []           _          (b:brr)    = b*aCut + solve1 aCut      []  undefined brr
    solve1    _          (a:arr)      bCut       []         = a*bCut + solve1 undefined arr bCut      []
    solve1    aCut       (a:arr)      bCut       (b:brr)
      | a &gt; b     = ((a*bCut) `rem` p + solve1 (aCut+1) arr     bCut    (b:brr)) `rem` p
      | otherwise = ((b*aCut) `rem` p + solve1 aCut     (a:arr) (bCut+1) brr   ) `rem` p

---------------------Input---------------------------- {{{
getInteger = (\(Just (x_yzpqr,_)) -&gt; x_yzpqr). BS.readInteger
getInt     = (\(Just (x_yzpqr,_)) -&gt; x_yzpqr). BS.readInt

getIntArray     = readIntArray
getIntegerArray = readIntegerArray

readIntArray input_pqr =
  case x_yzpqr of
    Just (a_yzpqr, xs_pqr) -&gt; a_yzpqr : readIntArray xs_pqr
    Nothing                -&gt; []
  where
    x_yzpqr = BS.readInt. BS.dropWhile isSpace $ input_pqr

readIntegerArray input_pqr =
  case x_yzpqr of
    Nothing               -&gt; []
    Just (y_zpqr, ys_pqr) -&gt; y_zpqr : readIntegerArray ys_pqr
  where
    x_yzpqr = BS.readInteger. BS.dropWhile isSpace $ input_pqr
------------------------------------------------------ }}}
</code></pre>

Reference solution (Python):
###Haskell  
```haskell  


-- {{{
module Main where
---------------------Import-------------------------
import Data.List
import qualified Data.Map as Map
import qualified Data.Set as Set
import Data.Char
import Data.Int                                     -- Int32, Int64
import System.IO
import Data.Ratio                                   -- x = 5%6
import Data.Bits                                    -- (.&.), (.|.), shiftL...
import Text.Printf                                  -- printf "%0.6f" (1.0)
import Control.Monad
import qualified Data.ByteString.Lazy.Char8 as BS
import qualified Data.Vector as V
import System.Directory
import System.FilePath
-- }}}
    
main :: IO ()
main = BS.getContents >>= mapM_ print. validate. map readIntegerArray. BS.lines
    
p :: Integer
p = 10^9+7
    
validate :: [[Integer]] -> [Integer]
validate ([t]: arr)
  | 3 * fromIntegral t /= length arr = error "t /= 3*length arr"
  | t < 0 || t > 20                  = error "t is out of bound"
  | otherwise                        = parse arr
    
parse :: [[Integer]] -> [Integer]
parse [] = []
parse ([n, m]: a: b: left)
  | n < 0 || n > 10^6               = error "n is out of range"
  | m < 0 || m > 10^6               = error "m is out of range"
  | fromIntegral n - 1 /= length a  = error "n - 1 /= length a"
  | fromIntegral m - 1 /= length b  = error "m - 1 /= length b"
  | any (\x -> x < 0 || x > 10^9) a = error "element of a is out of bound"
  | any (\x -> x < 0 || x > 10^9) b = error "element of a is out of bound"
  | otherwise = (solve a b): parse left
    
solve :: [Integer] -> [Integer] -> Integer
solve aa bb = solve1 1 (reverse. sort$ aa) 1 (reverse. sort $bb)
  where
    solve1 :: Integer -> [Integer] -> Integer -> [Integer] -> Integer
    solve1    _          []           _          []         = 0
    solve1    aCut       []           _          (b:brr)    = b*aCut + solve1 aCut      []  undefined brr
    solve1    _          (a:arr)      bCut       []         = a*bCut + solve1 undefined arr bCut      []
    solve1    aCut       (a:arr)      bCut       (b:brr)
      | a > b     = ((a*bCut) `rem` p + solve1 (aCut+1) arr     bCut    (b:brr)) `rem` p
      | otherwise = ((b*aCut) `rem` p + solve1 aCut     (a:arr) (bCut+1) brr   ) `rem` p
    
---------------------Input---------------------------- {{{
getInteger = (\(Just (x_yzpqr,_)) -> x_yzpqr). BS.readInteger
getInt     = (\(Just (x_yzpqr,_)) -> x_yzpqr). BS.readInt
    
getIntArray     = readIntArray
getIntegerArray = readIntegerArray
    
readIntArray input_pqr =
  case x_yzpqr of
    Just (a_yzpqr, xs_pqr) -> a_yzpqr : readIntArray xs_pqr
    Nothing                -> []
  where
    x_yzpqr = BS.readInt. BS.dropWhile isSpace $ input_pqr
    
readIntegerArray input_pqr =
  case x_yzpqr of
    Nothing               -> []
    Just (y_zpqr, ys_pqr) -> y_zpqr : readIntegerArray ys_pqr
  where
    x_yzpqr = BS.readInteger. BS.dropWhile isSpace $ input_pqr
------------------------------------------------------ }}}
    
```