Problem:
Score : 600 points

Problem Statement

Silver Fox is fighting with N monsters.

The monsters are standing in a row, and we can assume them to be standing on a number line. The i-th monster, standing at the coordinate X_i, has the health of H_i.

Silver Fox can use bombs to attack the monsters.
Using a bomb at the coordinate x decreases the healths of all monsters between the coordinates x-D and x+D (inclusive) by A.
There is no way other than bombs to decrease the monster's health.

Silver Fox wins when all the monsters' healths become 0 or below.

Find the minimum number of bombs needed to win.

Constraints

1 \leq N \leq 2 \times 10^5

0 \leq D \leq 10^9

1 \leq A \leq 10^9

0 \leq X_i \leq 10^9

1 \leq H_i \leq 10^9

X_i are distinct.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N D A
X_1 H_1
:
X_N H_N

Output

Print the minimum number of bombs needed to win.

Sample Input 1

3 3 2
1 2
5 4
9 2

Sample Output 1

2

First, let us use a bomb at the coordinate 4 to decrease the first and second monsters' health by 2.

Then, use a bomb at the coordinate 6 to decrease the second and third monsters' health by 2.

Now, all the monsters' healths are 0.
We cannot make all the monsters' health drop to 0 or below with just one bomb.

Sample Input 2

9 4 1
1 5
2 4
3 3
4 2
5 1
6 2
7 3
8 4
9 5

Sample Output 2

5

We should use five bombs at the coordinate 5.

Sample Input 3

3 0 1
300000000 1000000000
100000000 1000000000
200000000 1000000000

Sample Output 3

3000000000

Watch out for overflow.

Solution in C# (.NET Core 3.1.201) (judge verdict: Time Limit Exceeded)

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

internal static class CR
{
    public static string Get() { return Console.ReadLine(); }
    public static IEnumerable<string> GetTexts() { return Console.ReadLine().Split(' '); }
    public static int GetInteger() { return int.Parse(Console.ReadLine()); }
    public static IEnumerable<long> GetIntegers() { return Console.ReadLine().Split(' ').Select(x => long.Parse(x)); }
}

namespace AtCoder.F
{
    public class Program
    {
        public static long N { get; private set; }
        public static long D { get; private set; }
        public static long A { get; private set; }

        public static void Main() { var r = GetResult(); Debug.WriteLine(r); Console.Write(r); }

        private static object GetResult()
        {
            var inputs = CR.GetIntegers().ToList();
            N = inputs[0];
            D = inputs[1];
            A = inputs[2];
            var monsters = new List<Monster>();
            for (int i = 0; i < N; i++)
            {
                inputs = CR.GetIntegers().ToList();
                monsters.Add(new Monster { X = inputs[0], H = inputs[1] });
            }

            monsters = monsters.OrderBy(x => x.X).ToList();
            var maxH = monsters.Max(x => x.H);

            var l = 0L;
            var r = (maxH / A + 1) * N;
            while (r - l != 1)
            {
                var mid = (l + r) / 2;
                if (CanKillAllMonster(mid, monsters))
                {
                    r = mid;
                }
                else
                {
                    l = mid;
                }
            }

            return r;
        }

        private static bool CanKillAllMonster(long maxAttackCount, List<Monster> monsters)
        {
            var attackCountSum = 0L;
            //var damages = new long[N];
            var attackInfo = new List<AttackInfo>();
            for (int i = 0; i < N; i++)
            {
                var startMonster = monsters[i];

                var damage = attackInfo.Where(x => x.MaxX >= startMonster.X).Sum(x => x.Damage);
                if (monsters[i].H <= damage) continue;

                var count = (long)Math.Ceiling((double)(startMonster.H - damage) / A);
                attackCountSum += count;

                if (attackCountSum > maxAttackCount) return false;

                attackInfo.Add(new AttackInfo { Damage = count * A, MaxX = startMonster.X + 2 * D });
                //damages[i] += damage;
                //for (int j = i + 1; j < N; j++)
                //{
                //    var nextMonster = monsters[j];
                //    // 当たらない
                //    if (nextMonster.X > startMonster.X + 2 * D)
                //    {
                //        break;
                //    }
                //    else
                //    {
                //        damages[j] += damage;
                //    }
                //}
            }

            return true;
        }
    }

    internal class AttackInfo
    {
        public long Damage { get; set; }
        public long MaxX { get; set; }
    }

    class Monster
    {
        public long X { get; set; }
        public long H { get; set; }
    }
}