

import operator

class SegmentTree:

    def __init__(self, size, fn=operator.add, default=None, initial_values=None):

        """

        :param int size:

        :param callable fn: 区間に適用する関数。引数を 2 つ取る。min, max, operator.xor など

        :param default:

        :param list initial_values:

        """

        default = default or 0



        # size 以上である最小の 2 冪を size とする

        n = 1

        while n < size:

            n *= 2

        self._size = n

        self._fn = fn



        self._tree = [default] * (self._size * 2 - 1)

        if initial_values:

            i = self._size - 1

            for v in initial_values:

                self._tree[i] = v

                i += 1

            i = self._size - 2

            while i >= 0:

                self._tree[i] = self._fn(self._tree[i * 2 + 1], self._tree[i * 2 + 2])

                i -= 1



    def set(self, i, value):

        """

        i 番目に value を設定

        :param int i:

        :param value:

        :return:

        """

        x = self._size - 1 + i

        self._tree[x] = value



        while x > 0:

            x = (x - 1) // 2

            self._tree[x] = self._fn(self._tree[x * 2 + 1], self._tree[x * 2 + 2])



    def add(self, i, value):

        """

        もとの i 番目と value に fn を適用したものを i 番目に設定

        :param int i:

        :param value:

        :return:

        """

        x = self._size - 1 + i

        self.set(i, self._fn(self._tree[x], value))



    def get(self, from_i, to_i=None, k=0, L=None, r=None):

        """

        [from_i, to_i) に fn を適用した結果を返す

        :param int from_i:

        :param int to_i:

        :param int k: self._tree[k] が、[L, r) に fn を適用した結果を持つ

        :param int L:

        :param int r:

        :return:

        """

        if to_i is None:

            return self._tree[self._size - 1 + from_i]



        L = 0 if L is None else L

        r = self._size if r is None else r



        if from_i <= L and r <= to_i:

            return self._tree[k]



        if to_i <= L or r <= from_i:

            return None



        ret_L = self.get(from_i, to_i, k * 2 + 1, L, (L + r) // 2)

        ret_r = self.get(from_i, to_i, k * 2 + 2, (L + r) // 2, r)

        if ret_L is None:

            return ret_r

        if ret_r is None:

            return ret_L

        return self._fn(ret_L, ret_r)



    def __len__(self):

        return self._size







from bisect import bisect_right

def resolve():

    N, D, A = list(map(int, input().split()))

    AB = [list(map(int, input().split())) for _ in range(N)]

    AB.sort()

    X, _ = list(zip(*AB))

    D = 2*D



    seg = SegmentTree(N+10)

    ans = 0

    for i, (x, h) in enumerate(AB):

        h = -(-h // A)

        damage = seg.get(0, i+1)



        if h < damage:

            continue

        ans += h - damage

        seg.add(i, h-damage)

        seg.add(bisect_right(X, x + D), - h + damage)

    print(ans)





if __name__ == "__main__":

    resolve()





class LasySegmentTree:

    def __init__(self, size: int, segfunc, lazy_ide_ele=0):

        self.lazy_ide_ele = lazy_ide_ele

        self.segfunc = segfunc

        self.N0 = 1 << (size - 1).bit_length()

        self.lazy = [self.lazy_ide_ele] * (2 * self.N0)



    def gindex(self, left, right):

        L = left + self.N0

        R = right + self.N0

        lm = (L // (L & -L)) >> 1

        rm = (R // (R & -R)) >> 1

        while L < R:

            if R <= rm:

                yield R

            if L <= lm:

                yield L

            L >>= 1

            R >>= 1

        while L:

            yield L

            L >>= 1



    def propagates(self, *ids):

        for i in reversed(ids):

            idx = i - 1

            v = self.lazy[idx]

            if v == self.lazy_ide_ele:

                continue

            self.lazy[2 * idx + 1] = self.segfunc(self.lazy[2 * idx + 1], v)

            self.lazy[2 * idx + 2] = self.segfunc(self.lazy[2 * idx + 2], v)

            self.lazy[idx] = self.lazy_ide_ele



    def update(self, left: int, right: int, x):

        L = self.N0 + left

        R = self.N0 + right



        while L < R:

            if R & 1:

                R -= 1

                self.lazy[R - 1] = self.segfunc(self.lazy[R - 1], x)

            if L & 1:

                self.lazy[L - 1] = self.segfunc(self.lazy[L - 1], x)

                L += 1

            L >>= 1

            R >>= 1



    def query(self, k: int):

        self.propagates(*self.gindex(k, k + 1))

        return self.lazy[k + self.N0 - 1]







from operator import add

from bisect import bisect_right

def resolve():

    N, D, A = list(map(int, input().split()))

    AB = [list(map(int, input().split())) for _ in range(N)]

    AB.sort()

    X, _ = list(zip(*AB))





    seg_lazy = LasySegmentTree(N+10, segfunc=add)

    ans = 0

    for i in range(N):

        d = AB[i][1] - seg_lazy.query(i)

        if d <= 0:

            continue

        cnt = -(-d//A)

        ans += cnt

        idx = bisect_right(X, (X[i] + 2*D))

        seg_lazy.update(i, idx, cnt*A)

    print(ans)





if __name__ == "__main__":

    resolve()
import operator


class SegmentTree:
    def __init__(self, size, fn=operator.add, default=None, initial_values=None):
        """
        :param int size:
        :param callable fn: 区間に適用する関数。引数を 2 つ取る。min, max, operator.xor など
        :param default:
        :param list initial_values:
        """
        default = default or 0
        # size 以上である最小の 2 冪を size とする
        n = 1
        while n < size:
            n *= 2
        self._size = n
        self._fn = fn
        self._tree = [default] * (self._size * 2 - 1)
        if initial_values:
            i = self._size - 1
            for v in initial_values:
                self._tree[i] = v
                i += 1
            i = self._size - 2
            while i >= 0:
                self._tree[i] = self._fn(self._tree[i * 2 + 1], self._tree[i * 2 + 2])
                i -= 1

    def set(self, i, value):
        """
        i 番目に value を設定
        :param int i:
        :param value:
        :return:
        """
        x = self._size - 1 + i
        self._tree[x] = value
        while x > 0:
            x = (x - 1) // 2
            self._tree[x] = self._fn(self._tree[x * 2 + 1], self._tree[x * 2 + 2])

    def add(self, i, value):
        """
        もとの i 番目と value に fn を適用したものを i 番目に設定
        :param int i:
        :param value:
        :return:
        """
        x = self._size - 1 + i
        self.set(i, self._fn(self._tree[x], value))

    def get(self, from_i, to_i=None, k=0, L=None, r=None):
        """
        [from_i, to_i) に fn を適用した結果を返す
        :param int from_i:
        :param int to_i:
        :param int k: self._tree[k] が、[L, r) に fn を適用した結果を持つ
        :param int L:
        :param int r:
        :return:
        """
        if to_i is None:
            return self._tree[self._size - 1 + from_i]
        L = 0 if L is None else L
        r = self._size if r is None else r
        if from_i <= L and r <= to_i:
            return self._tree[k]
        if to_i <= L or r <= from_i:
            return None
        ret_L = self.get(from_i, to_i, k * 2 + 1, L, (L + r) // 2)
        ret_r = self.get(from_i, to_i, k * 2 + 2, (L + r) // 2, r)
        if ret_L is None:
            return ret_r
        if ret_r is None:
            return ret_L
        return self._fn(ret_L, ret_r)

    def __len__(self):
        return self._size


from bisect import bisect_right


def resolve():
    N, D, A = list(map(int, input().split()))
    AB = [list(map(int, input().split())) for _ in range(N)]
    AB.sort()
    X, _ = list(zip(*AB))
    D = 2 * D
    seg = SegmentTree(N + 10)
    ans = 0
    for i, (x, h) in enumerate(AB):
        h = -(-h // A)
        damage = seg.get(0, i + 1)
        if h < damage:
            continue
        ans += h - damage
        seg.add(i, h - damage)
        seg.add(bisect_right(X, x + D), -h + damage)
    print(ans)


if __name__ == "__main__":
    resolve()

class LasySegmentTree:
    def __init__(self, size: int, segfunc, lazy_ide_ele=0):
        self.lazy_ide_ele = lazy_ide_ele
        self.segfunc = segfunc
        self.N0 = 1 << (size - 1).bit_length()
        self.lazy = [self.lazy_ide_ele] * (2 * self.N0)

    def gindex(self, left, right):
        L = left + self.N0
        R = right + self.N0
        lm = (L // (L & -L)) >> 1
        rm = (R // (R & -R)) >> 1
        while L < R:
            if R <= rm:
                yield R
            if L <= lm:
                yield L
            L >>= 1
            R >>= 1
        while L:
            yield L
            L >>= 1

    def propagates(self, *ids):
        for i in reversed(ids):
            idx = i - 1
            v = self.lazy[idx]
            if v == self.lazy_ide_ele:
                continue
            self.lazy[2 * idx + 1] = self.segfunc(self.lazy[2 * idx + 1], v)
            self.lazy[2 * idx + 2] = self.segfunc(self.lazy[2 * idx + 2], v)
            self.lazy[idx] = self.lazy_ide_ele

    def update(self, left: int, right: int, x):
        L = self.N0 + left
        R = self.N0 + right
        while L < R:
            if R & 1:
                R -= 1
                self.lazy[R - 1] = self.segfunc(self.lazy[R - 1], x)
            if L & 1:
                self.lazy[L - 1] = self.segfunc(self.lazy[L - 1], x)
                L += 1
            L >>= 1
            R >>= 1

    def query(self, k: int):
        self.propagates(*self.gindex(k, k + 1))
        return self.lazy[k + self.N0 - 1]


from operator import add
from bisect import bisect_right


def resolve():
    N, D, A = list(map(int, input().split()))
    AB = [list(map(int, input().split())) for _ in range(N)]
    AB.sort()
    X, _ = list(zip(*AB))
    seg_lazy = LasySegmentTree(N + 10, segfunc=add)
    ans = 0
    for i in range(N):
        d = AB[i][1] - seg_lazy.query(i)
        if d <= 0:
            continue
        cnt = -(-d // A)
        ans += cnt
        idx = bisect_right(X, (X[i] + 2 * D))
        seg_lazy.update(i, idx, cnt * A)
    print(ans)


if __name__ == "__main__":
    resolve()

-import operator +class LasySegmentTree: +    def __init__(self, size: int, segfunc, lazy_ide_ele=0): +        self.lazy_ide_ele = lazy_ide_ele +        self.segfunc = segfunc +        self.N0 = 1 << (size - 1).bit_length() +        self.lazy = [self.lazy_ide_ele] * (2 * self.N0) + +    def gindex(self, left, right): +        L = left + self.N0 +        R = right + self.N0 +        lm = (L // (L & -L)) >> 1 +        rm = (R // (R & -R)) >> 1 +        while L < R: +            if R <= rm: +                yield R +            if L <= lm: +                yield L +            L >>= 1 +            R >>= 1 +        while L: +            yield L +            L >>= 1 + +    def propagates(self, *ids): +        for i in reversed(ids): +            idx = i - 1 +            v = self.lazy[idx] +            if v == self.lazy_ide_ele: +                continue +            self.lazy[2 * idx + 1] = self.segfunc(self.lazy[2 * idx + 1], v) +            self.lazy[2 * idx + 2] = self.segfunc(self.lazy[2 * idx + 2], v) +            self.lazy[idx] = self.lazy_ide_ele + +    def update(self, left: int, right: int, x): +        L = self.N0 + left +        R = self.N0 + right +        while L < R: +            if R & 1: +                R -= 1 +                self.lazy[R - 1] = self.segfunc(self.lazy[R - 1], x) +            if L & 1: +                self.lazy[L - 1] = self.segfunc(self.lazy[L - 1], x) +                L += 1 +            L >>= 1 +            R >>= 1 + +    def query(self, k: int): +        self.propagates(*self.gindex(k, k + 1)) +        return self.lazy[k + self.N0 - 1] -class SegmentTree: -    def __init__(self, size, fn=operator.add, default=None, initial_values=None): -        """ -        :param int size: -        :param callable fn: 区間に適用する関数。引数を 2 つ取る。min, max, operator.xor など -        :param default: -        :param list initial_values: -        """ -        default = default or 0 -        # size 以上である最小の 2 冪を size とする -        n = 1 -        while n < size: -            n *= 2 -        self._size = n -        self._fn = fn -        self._tree = [default] * (self._size * 2 - 1) -        if initial_values: -            i = self._size - 1 -            for v in initial_values: -                self._tree[i] = v -                i += 1 -            i = self._size - 2 -            while i >= 0: -                self._tree[i] = self._fn(self._tree[i * 2 + 1], self._tree[i * 2 + 2]) -                i -= 1 - -    def set(self, i, value): -        """ -        i 番目に value を設定 -        :param int i: -        :param value: -        :return: -        """ -        x = self._size - 1 + i -        self._tree[x] = value -        while x > 0: -            x = (x - 1) // 2 -            self._tree[x] = self._fn(self._tree[x * 2 + 1], self._tree[x * 2 + 2]) - -    def add(self, i, value): -        """ -        もとの i 番目と value に fn を適用したものを i 番目に設定 -        :param int i: -        :param value: -        :return: -        """ -        x = self._size - 1 + i -        self.set(i, self._fn(self._tree[x], value)) - -    def get(self, from_i, to_i=None, k=0, L=None, r=None): -        """ -        [from_i, to_i) に fn を適用した結果を返す -        :param int from_i: -        :param int to_i: -        :param int k: self._tree[k] が、[L, r) に fn を適用した結果を持つ -        :param int L: -        :param int r: -        :return: -        """ -        if to_i is None: -            return self._tree[self._size - 1 + from_i] -        L = 0 if L is None else L -        r = self._size if r is None else r -        if from_i <= L and r <= to_i: -            return self._tree[k] -        if to_i <= L or r <= from_i: -            return None -        ret_L = self.get(from_i, to_i, k * 2 + 1, L, (L + r) // 2) -        ret_r = self.get(from_i, to_i, k * 2 + 2, (L + r) // 2, r) -        if ret_L is None: -            return ret_r -        if ret_r is None: -            return ret_L -        return self._fn(ret_L, ret_r) - -    def __len__(self): -        return self._size - - +from operator import add -    D = 2 * D -    seg = SegmentTree(N + 10) +    seg_lazy = LasySegmentTree(N + 10, segfunc=add) -    for i, (x, h) in enumerate(AB): -        h = -(-h // A) -        damage = seg.get(0, i + 1) -        if h < damage: +    for i in range(N): +        d = AB[i][1] - seg_lazy.query(i) +        if d <= 0: -        ans += h - damage -        seg.add(i, h - damage) -        seg.add(bisect_right(X, x + D), -h + damage) +        cnt = -(-d // A) +        ans += cnt +        idx = bisect_right(X, (X[i] + 2 * D)) +        seg_lazy.update(i, idx, cnt * A)