#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define pi pair<ll, ll>
#define mp make_pair
#define pb push_back
#define vi vector<ll>
#define pd pair<double, double>
#define vp vector<pi>
#define f(i, n) for(int i = 0; i < n; i++)
#define fo(i, a, n) for(int i = a; i < n; i++)
#define mod (1000*1000*1000+7)
#define sz(x) int((x).size())
#define all(x) x.begin(),x.end()
#define DBG(v) cerr << #v << " = " << (v) << endl;
ll INF = (1ll<<31);

using namespace std;

template<class V, class U> struct SegTree {
	int n;
	vector<V> st;
	vector<U> lazy;
	vector<int> leaves;

	SegTree(const int n) : n(n) {
		leaves.resize(n);
		init(1, 0, n - 1);
		lazy.resize(st.size());
	}

	void init(const int si, const int lo, const int hi) { // init st[] and leaves[]
		if (lo == hi) {
			if(si >= (int)st.size()) st.resize(si + 1);
			st[si] = V(); // optional if V(V(), V()) = V() ---- | ---- cin >> ??
			leaves[lo] = si;
		} else {
			const int mid = (lo + hi) >> 1;
			init(si << 1, lo, mid);
			init(si << 1 | 1, mid + 1, hi);
			st[si] = V(st[si << 1], st[si << 1 | 1]); // optional if T(T(), T()) = T()
		}
	}

	void updateLazy(const int si, const int lo, const int hi) {
		lazy[si].apply(st[si], lo, hi);
		if (lo != hi) {
			lazy[si << 1] = U(lazy[si << 1], lazy[si]);
			lazy[si << 1 | 1] = U(lazy[si << 1 | 1], lazy[si]);
		}
		lazy[si] = U();
	}

	V query(const int l, const int r) { return (l <= r && l < n && r >= 0) ? query(l, r, 1, 0, n - 1) : V(); }
	V query(const int l, const int r, const int si, const int lo, const int hi) {
		updateLazy(si, lo, hi);
		if (l <= lo && hi <= r) return st[si];

		const int mid = (lo + hi) >> 1;
		if (r <= mid) return query(l, r, si << 1, lo, mid);
		if (mid < l) return query(l, r, si << 1 | 1, mid + 1, hi);
		return V(query(l, r, si << 1, lo, mid), query(l, r, si << 1 | 1, mid + 1, hi));
	}


	void update(const int l, const int r, const U u) { if (l <= r) update(l, r, u, 1, 0, n - 1); }
	void update(const int l, const int r, const U &u, const int si, const int lo, const int hi) {
		if (l <= lo && hi <= r) {
			lazy[si] = U(lazy[si], u);
			updateLazy(si, lo, hi);
		} else {
			updateLazy(si, lo, hi);
			if (hi < l || r < lo) return;
			const int mid = (lo + hi) >> 1;
			update(l, r, u, si << 1, lo, mid);
			update(l, r, u, si << 1 | 1, mid + 1, hi);
			st[si] = V(st[si << 1], st[si << 1 | 1]);
		}
	}
};

struct StVal { // define
	ll v = 0; // optional
	StVal() {}
	StVal(const ll v) : v(v) {} // optional
	StVal(const StVal &v1, const StVal &v2) { v = v1 + v2; }
	operator ll() const { return v; } // optional
};

struct StUpdate { // define
	ll v = 0; // optional
	StUpdate() {}
	StUpdate(const ll v) : v(v) {} // optional
	StUpdate(const StUpdate &u1, const StUpdate &u2) { v = u1 + u2; }
	operator ll() const { return v; } // optional
	void apply(StVal &v, const int lo, const int hi) { // omit last 2 arguments if non-lazy segment tree
		v.v += this->v * (hi - lo + 1);
	}
};

typedef SegTree<StVal, StUpdate> MyST;

int main(int argc, char* argv[])
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    ll n, d, a; cin >> n >> d >> a;
    vp v(n);
    vi inv;
    unordered_map<ll, ll> cvt;
    f(i, n){
      cin >> v[i].first >> v[i].second;
      inv.pb(v[i].first);
      inv.pb(v[i].first+2*d);
    }
    sort(all(v));
    sort(all(inv));
    f(i, sz(inv)){
      cvt[inv[i]] = i;
    }
    MyST st(1e6+5);
    f(i, sz(v)){
      st.update(cvt[v[i].first], cvt[v[i].first], v[i].second);
    }
    ll ans = 0;
    f(i, sz(v)){
      ll y = cvt[v[i].first];
      ll z = cvt[v[i].first + 2 * d];
      if(st.query(y, y) <= 0) continue;
      ll x = (st.query(y,y) + (a-1))/a;
      st.update(y, z, -x*a);
      // DBG(x)
      ans += x;
    }
    cout << ans << endl;
    return 0;
}


Measured memory_bytes: 60136