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

public class Program
{
    private int N, D, A;
    private S[] XH;

    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        D = sc.NextInt();
        A = sc.NextInt();
        XH = new S[N];
        for (int i = 0; i < N; i++)
        {
            XH[i] = new S(sc.NextInt(), sc.NextInt());
        }

        Array.Sort(XH, (a, b) => a.X.CompareTo(b.X));

        var ruq = new RangeUpdateQuery<long>((a, b) => a + b, 0);
        for (int i = 0; i < N; i++)
        {
            ruq.Update(i, i + 1, XH[i].H);
        }

        var set = new Set<long>();
        for (int i = 0; i < N; i++)
        {
            set.Add(XH[i].X);
        }

        long ans = 0;
        for (int i = 0; i < N; i++)
        {
            long c = ruq[i];
            if (c <= 0) continue;
            long cnt = (c + A - 1) / A;
            int right = set.UpperBound(XH[i].X + D + D);
            ans += cnt;
            ruq.Update(i, right, -(A * cnt));
        }

        Console.WriteLine(ans);
    }

    public static void Main(string[] args)
    {
        new Program().Solve();
    }
}

struct S
{
    public long X, H;

    public S(long x, long h)
    {
        X = x;
        H = h;
    }
}

namespace CompLib.Collections.Generic
{
    using System;

    public class RangeUpdateQuery<T>
    {
        // 制約に合った2の冪
        private const int N = 1 << 21;
        private T[] _array;
        private readonly bool[] flag;

        private readonly T _identity;
        private readonly Func<T, T, T> _operation;

        /// <summary>
        /// 区間更新、点取得
        /// </summary>
        /// <param name="operation">更新用の演算</param>
        /// <param name="identity">(T, operation)の左単位元</param>
        public RangeUpdateQuery(Func<T, T, T> operation, T identity)
        {
            _identity = identity;
            _operation = operation;
            _array = new T[N * 2];
            for (int i = 1; i < N * 2; i++)
            {
                _array[i] = _identity;
            }

            flag = new bool[N * 2];
        }

        private void Eval(int k, int l, int r)
        {
            if (flag[k])
            {
                if (r - l > 1)
                {
                    _array[k * 2] = _operation(_array[k * 2], _array[k]);
                    flag[k * 2] = true;
                    _array[k * 2 + 1] = _operation(_array[k * 2 + 1], _array[k]);
                    flag[k * 2 + 1] = true;
                    _array[k] = _identity;
                }

                flag[k] = false;
            }
        }

        private void Update(int left, int right, int k, int l, int r, T item)
        {
            Eval(k, l, r);
            if (r <= left || right <= l)
            {
                return;
            }

            if (left <= l && r <= right)
            {
                _array[k] = _operation(_array[k], item);
                flag[k] = true;
                Eval(k, l, r);
                return;
            }

            Update(left, right, k * 2, l, (l + r) / 2, item);
            Update(left, right, k * 2 + 1, (l + r) / 2, r, item);
        }

        /// <summary> 
        /// [left,right)をoperation(A[i],item)に更新
        /// </summary>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <param name="item"></param>
        public void Update(int left, int right, T item)
        {
            Update(left, right, 1, 0, N, item);
        }


        /// <summary>
        /// A[i]を取得 O(log N)
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        public T Get(int i)
        {
            int l = 0;
            int r = N;
            int k = 1;
            while (r - l > 1)
            {
                Eval(k, l, r);
                int m = (l + r) / 2;
                if (i < m)
                {
                    r = m;
                    k = k * 2;
                }
                else
                {
                    l = m;
                    k = k * 2 + 1;
                }
            }

            return _array[k];
        }

        public T this[int i]
        {
            get { return Get(i); }
        }
    }
}

#region Set

public class Set<T>
{
    Node root;
    readonly IComparer<T> comparer;
    readonly Node nil;
    public bool IsMultiSet { get; set; }

    public Set(IComparer<T> comparer)
    {
        nil = new Node(default(T));
        root = nil;
        this.comparer = comparer;
    }

    public Set(Comparison<T> comaprison) : this(Comparer<T>.Create(comaprison))
    {
    }

    public Set() : this(Comparer<T>.Default)
    {
    }

    public bool Add(T v)
    {
        return insert(ref root, v);
    }

    public bool Remove(T v)
    {
        return remove(ref root, v);
    }

    public T this[int index]
    {
        get { return find(root, index); }
    }

    public int Count
    {
        get { return root.Count; }
    }

    public void RemoveAt(int k)
    {
        if (k < 0 || k >= root.Count) throw new ArgumentOutOfRangeException();
        removeAt(ref root, k);
    }

    public T[] Items
    {
        get
        {
            var ret = new T[root.Count];
            var k = 0;
            walk(root, ret, ref k);
            return ret;
        }
    }

    void walk(Node t, T[] a, ref int k)
    {
        if (t.Count == 0) return;
        walk(t.lst, a, ref k);
        a[k++] = t.Key;
        walk(t.rst, a, ref k);
    }

    bool insert(ref Node t, T key)
    {
        if (t.Count == 0)
        {
            t = new Node(key);
            t.lst = t.rst = nil;
            t.Update();
            return true;
        }

        var cmp = comparer.Compare(t.Key, key);
        bool res;
        if (cmp > 0)
            res = insert(ref t.lst, key);
        else if (cmp == 0)
        {
            if (IsMultiSet) res = insert(ref t.lst, key);
            else return false;
        }
        else res = insert(ref t.rst, key);

        balance(ref t);
        return res;
    }

    bool remove(ref Node t, T key)
    {
        if (t.Count == 0) return false;
        var cmp = comparer.Compare(key, t.Key);
        bool ret;
        if (cmp < 0) ret = remove(ref t.lst, key);
        else if (cmp > 0) ret = remove(ref t.rst, key);
        else
        {
            ret = true;
            var k = t.lst.Count;
            if (k == 0)
            {
                t = t.rst;
                return true;
            }

            if (t.rst.Count == 0)
            {
                t = t.lst;
                return true;
            }


            t.Key = find(t.lst, k - 1);
            removeAt(ref t.lst, k - 1);
        }

        balance(ref t);
        return ret;
    }

    void removeAt(ref Node t, int k)
    {
        var cnt = t.lst.Count;
        if (cnt < k) removeAt(ref t.rst, k - cnt - 1);
        else if (cnt > k) removeAt(ref t.lst, k);
        else
        {
            if (cnt == 0)
            {
                t = t.rst;
                return;
            }

            if (t.rst.Count == 0)
            {
                t = t.lst;
                return;
            }

            t.Key = find(t.lst, k - 1);
            removeAt(ref t.lst, k - 1);
        }

        balance(ref t);
    }

    void balance(ref Node t)
    {
        var balance = t.lst.Height - t.rst.Height;
        if (balance == -2)
        {
            if (t.rst.lst.Height - t.rst.rst.Height > 0)
            {
                rotR(ref t.rst);
            }

            rotL(ref t);
        }
        else if (balance == 2)
        {
            if (t.lst.lst.Height - t.lst.rst.Height < 0) rotL(ref t.lst);
            rotR(ref t);
        }
        else t.Update();
    }

    T find(Node t, int k)
    {
        if (k < 0 || k > root.Count) throw new ArgumentOutOfRangeException();
        for (;;)
        {
            if (k == t.lst.Count) return t.Key;
            else if (k < t.lst.Count) t = t.lst;
            else
            {
                k -= t.lst.Count + 1;
                t = t.rst;
            }
        }
    }

    public int LowerBound(T v)
    {
        var k = 0;
        var t = root;
        for (;;)
        {
            if (t.Count == 0) return k;
            if (comparer.Compare(v, t.Key) <= 0) t = t.lst;
            else
            {
                k += t.lst.Count + 1;
                t = t.rst;
            }
        }
    }

    public int UpperBound(T v)
    {
        var k = 0;
        var t = root;
        for (;;)
        {
            if (t.Count == 0) return k;
            if (comparer.Compare(t.Key, v) <= 0)
            {
                k += t.lst.Count + 1;
                t = t.rst;
            }
            else t = t.lst;
        }
    }

    void rotR(ref Node t)
    {
        var l = t.lst;
        t.lst = l.rst;
        l.rst = t;
        t.Update();
        l.Update();
        t = l;
    }

    void rotL(ref Node t)
    {
        var r = t.rst;
        t.rst = r.lst;
        r.lst = t;
        t.Update();
        r.Update();
        t = r;
    }


    class Node
    {
        public Node(T key)
        {
            Key = key;
        }

        public int Count { get; private set; }
        public sbyte Height { get; private set; }
        public T Key { get; set; }
        public Node lst, rst;

        public void Update()
        {
            Count = 1 + lst.Count + rst.Count;
            Height = (sbyte) (1 + Math.Max(lst.Height, rst.Height));
        }

        public override string ToString()
        {
            return string.Format("Count = {0}, Key = {1}", Count, Key);
        }
    }
}

#endregion

class Scanner
{
    public Scanner()
    {
        _pos = 0;
        _line = new string[0];
    }

    const char Separator = ' ';
    private int _pos;
    private string[] _line;

    #region スペース区切りで取得

    public string Next()
    {
        if (_pos >= _line.Length)
        {
            _line = Console.ReadLine().Split(Separator);
            _pos = 0;
        }

        return _line[_pos++];
    }

    public int NextInt()
    {
        return int.Parse(Next());
    }

    public long NextLong()
    {
        return long.Parse(Next());
    }

    public double NextDouble()
    {
        return double.Parse(Next());
    }

    #endregion

    #region 型変換

    private int[] ToIntArray(string[] array)
    {
        var result = new int[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = int.Parse(array[i]);
        }

        return result;
    }

    private long[] ToLongArray(string[] array)
    {
        var result = new long[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = long.Parse(array[i]);
        }

        return result;
    }

    private double[] ToDoubleArray(string[] array)
    {
        var result = new double[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = double.Parse(array[i]);
        }

        return result;
    }

    #endregion

    #region 配列取得

    public string[] Array()
    {
        if (_pos >= _line.Length)
            _line = Console.ReadLine().Split(Separator);

        _pos = _line.Length;
        return _line;
    }

    public int[] IntArray()
    {
        return ToIntArray(Array());
    }

    public long[] LongArray()
    {
        return ToLongArray(Array());
    }

    public double[] DoubleArray()
    {
        return ToDoubleArray(Array());
    }

    #endregion
}

Measured memory_bytes: 63132