Problem:
Score : 400 points

Problem Statement

There is a bar of chocolate with a height of H blocks and a width of W blocks.
Snuke is dividing this bar into exactly three pieces.
He can only cut the bar along borders of blocks, and the shape of each piece must be a rectangle.

Snuke is trying to divide the bar as evenly as possible.
More specifically, he is trying to minimize S_{max} - S_{min}, where S_{max} is the area (the number of blocks contained) of the largest piece, and S_{min} is the area of the smallest piece.
Find the minimum possible value of S_{max} - S_{min}.

Constraints

2 ≤ H, W ≤ 10^5

Input

Input is given from Standard Input in the following format:

H W

Output

Print the minimum possible value of S_{max} - S_{min}.

Sample Input 1

3 5

Sample Output 1

0

In the division below, S_{max} - S_{min} = 5 - 5 = 0.

Sample Input 2

4 5

Sample Output 2

2

In the division below, S_{max} - S_{min} = 8 - 6 = 2.

Sample Input 3

5 5

Sample Output 3

4

In the division below, S_{max} - S_{min} = 10 - 6 = 4.

Sample Input 4

100000 2

Sample Output 4

1

Sample Input 5

100000 100000

Sample Output 5

50000

Solution in Rust (1.15.1) (judge verdict: Accepted)

#![allow(non_snake_case, unused_imports)]

// Input
macro_rules! input { (source = $s:expr, $($r:tt)*) => { let mut iter = $s.split_whitespace(); let mut next = || { iter.next().unwrap() }; input_inner!{next, $($r)*} }; ($($r:tt)*) => { let stdin = std::io::stdin(); let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock())); let mut next = move || -> String{ bytes.by_ref().map(|r|r.unwrap() as char).skip_while(|c|c.is_whitespace()).take_while(|c|!c.is_whitespace()).collect() }; input_inner!{next, $($r)*} }; }
macro_rules! input_inner { ($next:expr) => {}; ($next:expr, ) => {}; ($next:expr, $var:ident : $t:tt $($r:tt)*) => { let $var = read_value!($next, $t); input_inner!{$next $($r)*} };}
macro_rules! read_value { ($next:expr, ( $($t:tt),* )) => { ( $(read_value!($next, $t)),* ) }; ($next:expr, [ $t:tt ; $len:expr ]) => { (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>() }; ($next:expr, chars) => { read_value!($next, String).chars().collect::<Vec<char>>() }; ($next:expr, bytes) => { read_value!($next, String).into_bytes() }; ($next:expr, usize1) => { read_value!($next, usize) - 1 }; ($next:expr, $t:ty) => { $next().parse::<$t>().expect("Parse error") }; }

// Module
use std::cmp::{min,max};
use std::collections::{HashSet,HashMap,BTreeMap,VecDeque};

// Functions

// Main
fn main(){
    input!{
        H: usize,
        W: usize,
    }
    let mut ans = 999999999;
    let (mut s1, mut s2, mut s3) = (1,1,1);
    // 高さで分割するのを全探索、一方を更に高さor幅で分割
    for h in 1..H{
        s1 = h*W;
        // 高さで分割
        s2 = ((H-h)/2)*W;
        s3 = (H-h-(H-h)/2)*W;
        ans = min(ans, max(s1,max(s2,s3))-min(s1,min(s2,s3)));
        // 幅で分割
        s2 = (H-h)*(W/2);
        s3 = (H-h)*(W-W/2);
        ans = min(ans, max(s1,max(s2,s3))-min(s1,min(s2,s3)));
    }
    // 高さと幅を入れ替えて再実行
    let (H,W) = (W,H);
    for h in 1..H{
        s1 = h*W;
        // 高さで分割
        s2 = ((H-h)/2)*W;
        s3 = (H-h-(H-h)/2)*W;
        ans = min(ans, max(s1,max(s2,s3))-min(s1,min(s2,s3)));
        // 幅で分割
        s2 = (H-h)*(W/2);
        s3 = (H-h)*(W-W/2);
        ans = min(ans, max(s1,max(s2,s3))-min(s1,min(s2,s3)));
    }
    println!("{}",ans);
}