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 Java8 (OpenJDK 1.8.0) (judge verdict: Accepted)

import java.io.*;
import java.util.Arrays;

/**
 * @author tutuz on 2020/03/29
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        MyInput in = new MyInput(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskX solver = new TaskX();
        solver.solve(1, in, out);
        out.close();
    }

    static int INF = 1 << 30;
    static long LINF = 1L << 55;
    static int MOD = 1000000007;
    static int[] mh4 = {0, -1, 1, 0};
    static int[] mw4 = {-1, 0, 0, 1};
    static int[] mh8 = {-1, -1, -1, 0, 0, 1, 1, 1};
    static int[] mw8 = {-1, 0, 1, -1, 1, -1, 0, 1};

    static class TaskX {

        public void solve(int testNumber, MyInput in, PrintWriter out) {
            int n = in.nextInt();
            long d = in.nextLong(), a = in.nextLong();
            P[] p = new P[n];
            for (int i = 0; i < n; i++) {
                int x = in.nextInt();
                int h = in.nextInt();
                p[i] = new P(x, h);
            }

            Arrays.sort(p);

            long[] imos = new long[n + 1];

            long ans = 0;
            for (int i = 0; i < n; i++) {
                if (p[i].second - imos[i] > 0) {
                    long base = p[i].first;
                    long cnt = (p[i].second - imos[i] + a - 1) / a;
                    ans += cnt;

                    int next = Bound.upperBound(p, i, n, base + 2 * d);
                    imos[next + 1] -= cnt * a;
                    imos[i] += cnt * a;
                }

                imos[i + 1] += imos[i];
            }

            out.println(ans);
        }
    }

    static class Bound {
        static int lowerBound(int[] a, int fromIndex, int toIndex, int key) {
            if (a[toIndex - 1] < key) {
                return toIndex;
            } else if (a[fromIndex] >= key) {
                return fromIndex;
            }
            int l = fromIndex;
            int r = toIndex - 1;
            while (l + 1 < r) {
                int c = (l + r) >>> 1;
                if (a[c] >= key) {
                    r = c;
                } else {
                    l = c;
                }
            }
            return r;
        }

        static int lowerBound(int[] a, int key) {
            return lowerBound(a, 0, a.length, key);
        }

        static int upperBound(P[] a, int fromIndex, int toIndex, long key) {
            if (a[toIndex - 1].first <= key) {
                return toIndex - 1;
            } else if (a[fromIndex].first > key) {
                return fromIndex - 1;
            }
            int l = fromIndex;
            int r = toIndex - 1;
            while (l + 1 < r) {
                int c = (l + r) >>> 1;
                if (a[c].first > key) {
                    r = c;
                } else {
                    l = c;
                }
            }
            return l;
        }

        static int upperBound(P[] a, int key) {
            return upperBound(a, 0, a.length, key);
        }
    }

    static class P implements Comparable<P> {
        long first, second;

        public P(long first, long second) {
            super();
            this.first = first;
            this.second = second;
        }

        @Override
        public String toString() {
            return "P [first=" + first + ", second=" + second + "]";
        }

        @Override
        public int compareTo(P p) {
            return Long.compare(this.first, p.first);
        }
    }
}

class MyInput {
    private final BufferedReader in;
    private static int pos;
    private static int readLen;
    private static final char[] buffer = new char[1024 * 8];
    private static char[] str = new char[500 * 8 * 2];
    private static boolean[] isDigit = new boolean[256];
    private static boolean[] isSpace = new boolean[256];
    private static boolean[] isLineSep = new boolean[256];

    static {
        for (int i = 0; i < 10; i++) {
            isDigit['0' + i] = true;
        }
        isDigit['-'] = true;
        isSpace[' '] = isSpace['\r'] = isSpace['\n'] = isSpace['\t'] = true;
        isLineSep['\r'] = isLineSep['\n'] = true;
    }

    public MyInput(InputStream is) {
        in = new BufferedReader(new InputStreamReader(is));
    }

    public int read() {
        if (pos >= readLen) {
            pos = 0;
            try {
                readLen = in.read(buffer);
            } catch (IOException e) {
                throw new RuntimeException();
            }
            if (readLen <= 0) {
                throw new EndOfFileRuntimeException();
            }
        }
        return buffer[pos++];
    }

    public int nextInt() {
        int len = 0;
        str[len++] = nextChar();
        len = reads(len, isSpace);
        int i = 0;
        int ret = 0;
        if (str[0] == '-') {
            i = 1;
        }
        for (; i < len; i++)
            ret = ret * 10 + str[i] - '0';
        if (str[0] == '-') {
            ret = -ret;
        }
        return ret;
    }

    public long nextLong() {
        int len = 0;
        str[len++] = nextChar();
        len = reads(len, isSpace);
        int i = 0;
        long ret = 0;
        if (str[0] == '-') {
            i = 1;
        }
        for (; i < len; i++)
            ret = ret * 10 + str[i] - '0';
        if (str[0] == '-') {
            ret = -ret;
        }
        return ret;
    }

    public char nextChar() {
        while (true) {
            final int c = read();
            if (!isSpace[c]) {
                return (char) c;
            }
        }
    }

    public String nextString() {
        return new String(nextChars());
    }

    public char[] nextChars() {
        int len = 0;
        str[len++] = nextChar();
        len = reads(len, isSpace);
        return Arrays.copyOf(str, len);
    }

    public char[][] next2DChars(int h, int w) {
        char[][] s = new char[h][w];
        for (int i = 0; i < h; i++) {
            s[i] = nextChars();
        }
        return s;
    }

    int reads(int len, boolean[] accept) {
        try {
            while (true) {
                final int c = read();
                if (accept[c]) {
                    break;
                }
                if (str.length == len) {
                    char[] rep = new char[str.length * 3 / 2];
                    System.arraycopy(str, 0, rep, 0, str.length);
                    str = rep;
                }
                str[len++] = (char) c;
            }
        } catch (EndOfFileRuntimeException e) {
        }
        return len;
    }

    public int[] nextIntArray(final int n) {
        final int[] res = new int[n];
        for (int i = 0; i < n; i++) {
            res[i] = nextInt();
        }
        return res;
    }

    public int[] nextIntArray1Index(final int n) {
        final int[] res = new int[n + 1];
        for (int i = 1; i < n + 1; i++) {
            res[i] = nextInt();
        }
        return res;
    }

    public int[] nextIntArrayDec(final int n) {
        final int[] res = new int[n];
        for (int i = 0; i < n; i++) {
            res[i] = nextInt() - 1;
        }
        return res;
    }

    public long[] nextLongArray(final int n) {
        final long[] res = new long[n];
        for (int i = 0; i < n; i++) {
            res[i] = nextLong();
        }
        return res;
    }

    public long[] nextLongArray1Index(final int n) {
        final long[] res = new long[n + 1];
        for (int i = 1; i < n + 1; i++) {
            res[i] = nextLong();
        }
        return res;
    }

    public long[] nextLongArrayDec(final int n) {
        final long[] res = new long[n];
        for (int i = 0; i < n; i++) {
            res[i] = nextLong() - 1;
        }
        return res;
    }

    public double nextDouble() {
        return Double.parseDouble(nextString());
    }

    public double[] nextDoubleArray(int n) {
        double[] res = new double[n];
        for (int i = 0; i < n; i++) {
            res[i] = nextDouble();
        }
        return res;
    }

    static class EndOfFileRuntimeException extends RuntimeException {
    }

}