#include<algorithm>
#include<bitset>
#include<cassert>
#include<cfloat>
#include<climits>
#include<cmath>
#include<deque>
#include<functional>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<string>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<vector>

using namespace std;

using lint = long long;
using P = pair<int, int>;
using LLP = pair<long long, long long>;

#define REP(i, x, n) for(int i = (x), i##_len = (int)(n) ; i < i##_len ; ++i)
#define rep(i, n) for(int i = 0, i##_len = (int)(n) ; i < i##_len ; ++i)
#define reps(i, n) for(int i = 1, i##_len = (int)(n) ; i <= i##_len ; ++i)
#define rrep(i, n) for(int i = (int)(n) - 1 ; i >= 0 ; --i)
#define rreps(i, n) for(int i = (int)(n) ; i > 0 ; --i)
#define SORT(x) sort((x).begin(), (x).end())
#define SORT_INV(x) sort((x).rbegin(), (x).rend())
#define REVERSE(x) reverse((x).begin(), (x).end())
#define TWINS(x) cout << ((x) ? "Yay!" : ":(") << '\n'
#define endl '\n'

constexpr int IINF = (1 << 30) - 1;
constexpr long long LLINF = 1LL << 61;
constexpr double EPS = 1e-10;

constexpr int dx4[] = {1, 0, -1, 0}, dy4[] = {0, 1, 0, -1};
constexpr int dx8[] = {1, 1, 0, -1, -1, -1, 0, 1}, dy8[] = {0, -1, -1, -1, 0, 1, 1, 1};

template<typename T>
bool chmax(T& a, T b){
    if(a < b){
        a = b;
        return true;
    }
    return false;
}

template<typename T>
bool chmin(T& a, T b){
    if(b < a){
        a = b;
        return true;
    }
    return false;
}

template<typename T>
class LazySegmentTree{
    int n;
    std::vector<T> node;
    std::vector<T> lazy;
    std::vector<int> length;
    int height;

    using F = std::function<T(T, T)>;
    using S = std::function<T(T, int)>;

    F f;
    F g;
    F h;
    S s;
    T id1;
    T id2;

    void evaluate(int k){
        if(lazy[k] == id2){
            return;
        }

        node[k] = g(node[k], s(lazy[k], length[k]));

        if(k < n){
            lazy[k << 1] = h(lazy[k << 1], lazy[k]);
            lazy[(k << 1) | 1] = h(lazy[(k << 1) | 1], lazy[k]);
        }

        lazy[k] = id2;

        return;
    }

    void evaluate(int l, int r){
        for(int i = height ; 0 < i ; --i){
            evaluate(l >> i);
            evaluate(r >> i);
        }

        return;
    }

public:
    LazySegmentTree(int n_, F f_, F g_, F h_, T id1_, T id2_, S s_ = [](T x, int len){ return x; }){
        init(n_, f_, g_, h_, id1_, id2_, s_);
    }

    LazySegmentTree(const std::vector<T>& dat, F f_, F g_, F h_, T id1_, T id2_, S s_ = [](T x, int len){ return x; }){
        build(dat, f_, g_, h_, id1_, id2_, s_);
    }

    void init(int n_, F f_, F g_, F h_, T id1_, T id2_, S s_ = [](T x, int len){ return x; }){
        n = 1;
        height = 0;
        while(n < n_){
            n <<= 1;
            ++height;
        }

        f = f_;
        g = g_;
        h = h_;
        id1 = id1_;
        id2 = id2_;
        s = s_;

        node.assign(n << 1, id1);
        lazy.assign(n << 1, id2);

        length.assign(n << 1, 1);
        fill(length.begin() + n + n_, length.end(), 0);
        for(int i = n - 1 ; 0 < i ; --i){
            length[i] = length[i << 1] + length[(i << 1) | 1];
        }

        return;
    }

    void build(const std::vector<T>& dat, F f_, F g_, F h_, T id1_, T id2_, S s_ = [](T x, int len){ return x; }){
        int n_ = (int)dat.size();

        init(n_, f_, g_, h_, id1_, id2_, s_);

        for(int i = 0 ; i < n_ ; ++i){
            node[i + n] = dat[i];
        }
        for(int i = n - 1 ; 0 < i ; --i){
            node[i] = f(node[i << 1], node[(i << 1) | 1]);
        }

        return;
    }

    void update(int l, int r, T x){
        l += n;
        r += n - 1;

        int L = l;
        int R = r;

        evaluate(l, r);

        ++r;

        while(l < r){
            if(r & 1){
                --r;
                lazy[r] = h(lazy[r], x);
            }
            r >>= 1;

            if(l & 1){
                lazy[l] = h(lazy[l], x);
                ++l;
            }
            l >>= 1;
        }

        while(L >>= 1, R >>= 1, L){
            evaluate(L << 1);
            evaluate((L << 1) | 1);
            node[L] = f(node[L << 1], node[(L << 1) | 1]);

            evaluate(R << 1);
            evaluate((R << 1) | 1);
            node[R] = f(node[R << 1], node[(R << 1) | 1]);
        }

        return;
    }

    T get(int l, int r){
        l += n;
        r += n - 1;

        evaluate(l, r);

        ++r;

        T res = id1;
        while(l < r){
            if(r & 1){
                --r;
                evaluate(r);
                res = f(res, node[r]);
            }
            r >>= 1;

            if(l & 1){
                evaluate(l);
                res = f(res, node[l]);
                ++l;
            }
            l >>= 1;
        }

        return res;
    }
};

template<typename T>
T meguru_search(T ok, T ng, function<bool(T)> check){
    while(max(ok, ng) - min(ok, ng) > T(1)){
        T mid = (ok + ng) / T(2);
        if(check(mid)){
            ok = mid;
        }else{
            ng = mid;
        }
    }
    return ok;
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);

    int n;
    lint d, a;
    cin >> n >> d >> a;

    vector< LLP > v;
    rep(i, n){
        lint x, h;
        cin >> x >> h;
        v.emplace_back(x, h);
    }

    SORT(v);

    LazySegmentTree<lint> seg(n, [](lint l, lint r){ return l + r; }, [](lint l, lint r){ return l + r; }, [](lint l, lint r){ return l + r; }, 0LL, 0LL, [](lint x, int len){ return x * len; });

    lint ans = 0;
    rep(i, n){
        lint t = seg.get(i, i + 1);
        if(t >= v[i].second){
            continue;
        }

        lint cnt = ((v[i].second - t) + a - 1LL) / a;
        ans += cnt;

        int r = meguru_search<int>(n, i, [&](int k){ return v[k].first > v[i].first + d * 2LL; });
        seg.update(i, r, cnt * a);
    }

    cout << ans << endl;

    cout << flush;

    return 0;
}

Measured memory_bytes: 14572