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 damageSum = 0L;
            var checkStartIndex = 0;
            var attackInfo = new List<AttackInfo>();
            for (int i = 0; i < N; i++)
            {
                var startMonster = monsters[i];

                // 届いていない攻撃のダメージを減算する
                for (int j = checkStartIndex; j < attackInfo.Count; j++)
                {
                    var atk = attackInfo[j];
                    if (startMonster.X > atk.MaxX)
                    {
                        damageSum -= atk.Damage;

                        // 端まで判定しきってしまった場合
                        if (j + 1 == attackInfo.Count)
                        {
                            checkStartIndex = j + 1;
                            break;
                        }
                    }
                    else
                    {
                        checkStartIndex = j;
                        break;
                    }
                }

                if (monsters[i].H <= damageSum) continue;

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

                if (attackCountSum > maxAttackCount) return false;

                attackInfo.Add(new AttackInfo { Damage = count * A, MaxX = startMonster.X + 2 * D });
                damageSum += count * A;
            }

            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; }
    }
}


Measured memory_bytes: 105992