Problem:
Score : 200 points

Problem Statement

We have a board with H horizontal rows and W vertical columns of squares.
There is a bishop at the top-left square on this board.
How many squares can this bishop reach by zero or more movements?

Here the bishop can only move diagonally.
More formally, the bishop can move from the square at the r_1-th row (from the top) and the c_1-th column (from the left) to the square at the r_2-th row and the c_2-th column if and only if exactly one of the following holds:

r_1 + c_1 = r_2 + c_2

r_1 - c_1 = r_2 - c_2

For example, in the following figure, the bishop can move to any of the red squares in one move:

Constraints

1 \leq H, W \leq 10^9

All values in input are integers.

Input

Input is given from Standard Input in the following format:

H \ W

Output

Print the number of squares the bishop can reach.

Sample Input 1

4 5

Sample Output 1

10

The bishop can reach the cyan squares in the following figure:

Sample Input 2

7 3

Sample Output 2

11

The bishop can reach the cyan squares in the following figure:

Sample Input 3

1000000000 1000000000

Sample Output 3

500000000000000000

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections.Generic;
using System.Linq;

public class Pana2003_B
{

    public static void Main()
    {
        double h = 0, w = 0;
        InLine(ref h, ref w);
        Out((long)Math.Ceiling(h * w / 2));
    }

    /* Template */
    private static object[] nullobj = null;

    //文字コード変換
    public static int ConvertInt(char c)
    {
        return c;
    }

    //入力:1入力配列
    public static A[] InArgs<A>(int count)
    {
        A[] var = default(A[]);
        InArgs(count, ref var, ref nullobj, ref nullobj);
        return var;
    }

    //入力:1入力配列
    public static void InArgs<A>(int count, ref A[] var)
    {
        InArgs(count, ref var, ref nullobj, ref nullobj);
    }

    //入力:2入力配列
    public static void InArgs<A, B>(int count, ref A[] var1, ref B[] var2)
    {
        InArgs(count, ref var1, ref var2, ref nullobj);
    }

    //入力:3入力配列
    public static void InArgs<A, B, C>(int count, ref A[] var1, ref B[] var2, ref C[] var3)
    {
        A a = default(A);
        B b = default(B);
        C c = default(C);
        for (int i = 0; i < count; i++)
        {
            InLine(ref a, ref b, ref c);
            var1[i] = a;
            if (var2 != null) var2[i] = b;
            if (var3 != null) var3[i] = c;
        }
    }

    //入力:1入力
    public static A InLine<A>()
    {
        A var = default(A);
        InLine(ref var);
        return var;
    }

    //入力:1入力
    public static void InLine<A>(ref A var)
    {
        InLine(ref var, ref nullobj, ref nullobj);
    }

    //入力:2入力
    public static void InLine<A, B>(ref A var1, ref B var2)
    {
        InLine(ref var1, ref var2, ref nullobj);
    }

    //入力:3入力
    public static void InLine<A, B, C>(ref A var1, ref B var2, ref C var3)
    {
        object[] o = new object[] { var1, var2, var3 };
        Type[] t = new Type[] { typeof(A), typeof(B), typeof(C) };
        if (var3 == null)
        {
            if (var2 == null) o = new object[] { var1 };
            else o = new object[] { var1, var2 };
        }

        var line = Console.ReadLine();
        string[] s;
        if (o.Length == 1) s = new string[1] { line };
        else s = line.Split(' ');
        for (int i = 0; i < s.Length; i++)
        {
            if (typeof(int) == t[i]) o[i] = int.Parse(s[i]);
            else if (typeof(long) == t[i]) o[i] = long.Parse(s[i]);
            else if (typeof(double) == t[i]) o[i] = double.Parse(s[i]);
            else o[i] = s[i];
        }
        var1 = (A)o[0];
        if (var2 != null) var2 = (B)o[1];
        if (var3 != null) var3 = (C)o[2];
    }

    //入力:1行配列
    public static A[] InLineArg<A>()
    {
        A[] var = default(A[]);
        InLineArg(ref var);
        return var;
    }

    //入力:1行配列
    public static void InLineArg<A>(ref A[] arg)
    {
        object obj = null;
        Type t = typeof(A);
        string[] line = Console.ReadLine().Split(' ');
        if (typeof(int) == t) obj = line.Select(int.Parse).ToArray();
        else if (typeof(long) == t) obj = line.Select(long.Parse).ToArray();
        else if (typeof(double) == t) obj = line.Select(double.Parse).ToArray();
        else obj = line;
        arg = (A[])obj;
    }

    //文字列結合
    public static string JoinString(object[] obj, string sep)
    {
        return string.Join(sep, obj.Select(i => i.ToString()).ToArray());
    }

    //出力
    public static void Out(object o)
    {
        Console.WriteLine(o);
    }

    //出力:Yes
    public static void OutYes()
    {
        Console.WriteLine("Yes");
    }

    //出力:No
    public static void OutNo()
    {
        Console.WriteLine("No");
    }

    //出力:YES
    public static void OutYES()
    {
        Console.WriteLine("YES");
    }

    //出力:NO
    public static void OutNO()
    {
        Console.WriteLine("NO");
    }

    //辞書生成
    private static Dictionary<A, B> PutDict<A, B>(A[] key, B[] value)
    {
        if (key.Length != value.Length) return null;
        var dic = new Dictionary<A, B>();
        for (int i = 0; i < key.Length; i++)
        {
            if (!dic.ContainsKey(key[i])) dic.Add(key[i], value[i]);
            else dic[key[i]] = value[i];
        }
        return dic;
    }

    //公約数
    public static int[] CommonDivisor(int num)
    {
        return CommonDivisor((long)num).Select(i => (int)i).ToArray();
    }

    public static long[] CommonDivisor(long num)
    {
        long l = 2, n = num;
        long[] result = new long[0];

        while (l * l <= num)
        {
            if (n % l == 0)
            {
                n /= l;
                Array.Resize(ref result, result.Length + 1);
                result[result.Length - 1] = l;
            }
            else l++;
        }
        if (n != 1)
        {
            Array.Resize(ref result, result.Length + 1);
            result[result.Length - 1] = n;
        }
        return result;
    }

    //大小比較
    public static bool Compare(bool equal, long a, long x)
    {
        return Compare(equal, a, x, long.MaxValue, true);
    }

    public static bool Compare(long x, long b, bool equal)
    {
        return Compare(true, long.MinValue, x, b, equal);
    }

    public static bool Compare(bool lequal, long a, long x, long b, bool requal)
    {
        if (a <= x && x <= b)
        {
            if (!lequal && x == a) return false;
            else if (!requal && x == b) return false;
            else return true;
        }
        return false;
    }

    //割り切る
    public static bool IsDivisible(long a, long b)
    {
        return a % b == 0;
    }

    //互いに素
    public static bool IsRelativelyPrime(long a, long b)
    {
        bool result = false;
        if (a > 1 && b > 1)
            result = CommonDivisor(a).Intersect(CommonDivisor(b)).ToArray().Length == 0;
        return result;
    }

    //素数判定
    public static bool IsPrimeNumber(int num)
    {
        if (num < 2) return false;
        else if (num == 2) return true;
        else if (num % 2 == 0) return false;

        double sqrtNum = Math.Sqrt(num);
        for (int i = 3; i <= sqrtNum; i += 2)
        {
            if (num % i == 0) return false;
        }
        return true;
    }

    //最大公約数
    public static int GCD(int a, int b)
    {
        return (int)GCD((long)a, b);
    }

    public static long GCD(long a, long b)
    {
        long[] acd = CommonDivisor(a).ToArray(), bcd = CommonDivisor(b).ToArray();
        Dictionary<long, int> dic1 = new Dictionary<long, int>(), dic2 = new Dictionary<long, int>();
        int count = 0;
        long n = 0, result = 1;
        for (int i = 0; i < acd.Length; i++)
        {
            if (n == acd[i]) count++;
            else
            {
                if (n != 0) dic1.Add(n, count);
                n = acd[i];
                count = 1;
            }
        }
        dic1.Add(n, count);
        n = 0;
        count = 0;
        for (int i = 0; i < bcd.Length; i++)
        {
            if (n == bcd[i]) count++;
            else
            {
                if (dic1.ContainsKey(n)) dic2[n] = Math.Max(count, dic1[n]);
                n = bcd[i];
                count = 1;
            }
        }
        if (dic1.ContainsKey(n)) dic2[n] = Math.Max(count, dic1[n]);
        foreach (long l in dic2.Keys)
        {
            result *= (long)Math.Pow(l, dic2[l]);
            Console.WriteLine($"{l}, {dic2[l]}");
        }
        return result;
    }

    //最小公倍数
    public static long LCM(long a, long b)
    {
        long[] acd = CommonDivisor(a).ToArray(), bcd = CommonDivisor(b).ToArray();
        var dic = new Dictionary<long, int>();
        int count = 0;
        long n = 0, result = 1;
        for (int i = 0; i < acd.Length; i++)
        {
            if (n == acd[i]) count++;
            else
            {
                if (n != 0) dic.Add(n, count);
                n = acd[i];
                count = 1;
            }
        }
        dic.Add(n, count);
        n = 0;
        count = 0;
        for (int i = 0; i < bcd.Length; i++)
        {
            if (n == bcd[i]) count++;
            else
            {
                if (dic.ContainsKey(n)) dic[n] = Math.Max(count, dic[n]);
                else if (n != 0) dic.Add(n, count);
                n = bcd[i];
                count = 1;
            }
        }
        if (dic.ContainsKey(n)) dic[n] = Math.Max(count, dic[n]);
        else dic.Add(n, count);
        foreach (long l in dic.Keys)
            result *= (long)Math.Pow(l, dic[l]);
        return result;
    }

    //組合せ数(nCr)
    public static double Combination(int n, int r)
    {
        if (n / 2 < r) r = n - r;
        return TotalPower(n, r + 1) / TotalPower(n - r);
    }

    //組合せ数総和(Σ(k=1,n,nCk))
    public static double CombinationSum(int n)
    {
        return Math.Pow(2, n);
    }

    //重複組合せ数(nHr)
    public static double RepetitionCombination(int n, int r)
    {
        return Combination(n + r - 1, r);
    }

    //重複組合せ数総和(Σ(k=1,n,nHk))
    public static double RepetitionCombinationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += RepetitionCombination(n, i);
        }
        return result;
    }

    //順列数(nPr)
    public static double Permutation(int n, int r)
    {
        return TotalPower(n, r + 1);
    }

    //順列数総和(Σ(k=1,n,nPk))
    public static double PermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += Permutation(n, i);
        }
        return result;
    }

    //円順列数
    public static double CircularPermutation(int n)
    {
        return TotalPower(n - 1);
    }

    //円順列数総和
    public static double CircularPermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += CircularPermutation(i);
        }
        return result;
    }



    //数珠順列数
    public static double NecklacePermutation(int n)
    {
        return CircularPermutation(n - 1) / 2;
    }

    //数珠順列数総和
    public static double NecklacePermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += NecklacePermutation(i);
        }
        return result;
    }

    //重複順列数(nΠr)
    public static double RepetitionPermutation(int n, int r)
    {
        return Math.Pow(n, r);
    }

    //重複順列数総和(Σ(k=1,n,nΠk))
    public static double RepetitionPermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += RepetitionPermutation(n, i);
        }
        return result;
    }

    //総乗
    public static double TotalPower(int max)
    {
        return TotalPower(max, 1);
    }

    public static double TotalPower(int max, int min)
    {
        double result = 1;
        for (int i = min; i <= max; i++) result *= i;
        return result;
    }

    public static double TotalPower(int[] ints)
    {
        double result = 1;
        foreach (int i in ints) result *= i;
        return result;
    }

    //総和
    public static double TotalSum(int max)
    {
        return TotalSum(max, 1);
    }

    public static double TotalSum(int max, int min)
    {
        double result = 1;
        for (int i = min; i <= max; i++) result += i;
        return result;
    }

    public static double TotalSum(int[] ints)
    {
        double result = 1;
        foreach (int i in ints) result += i;
        return result;
    }
}