//Compete against Yourself.
#include <bits/stdc++.h>
#define _ ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define int long long
#define sz(i) (int)(i.size())
#define F first
#define S second
#define L long double
#define P pair<int, int>
const int inf = 0x3f3f3f3f3f3f3f3LL;
const int mod = (int)1e9 + 7;
using namespace std;
#if LOCAL
#include "../../tr.h"
#else
#define tr(...)
#define endl '\n'
#endif
template<class T> void smin(T& a, T val) {if (a > val) a = val;}template<class T> void smax(T& a, T val) {if (a < val) a = val;}
const int N = 5*(int)1e5 + 10;

int n, d, maxHealth;
vector<vector<int>> X;

//Segment tree operations: Range update(Lazy propagation) and Range Query

const int MAX = 2*1e5 + 5;
const int LIM = 8e5 + 5;        //equals 2 * 2^ceil(log2(n))

int a[MAX];
int seg[LIM];
int lazy[LIM];
bool push[LIM];

//Complexity: O(1)
//Stores what info. segment[i..j] should store
int combine(int &a, int &b) {
   return max(a, b);
}

//Lazy propagation
void propagate(int t, int i, int j) {
   if (push[t]) {
      seg[t] = seg[t] + lazy[t];
      if (i != j) {
         push[t*2] = true;
         push[t*2 + 1] = true;
         lazy[t*2] = lazy[t*2] + lazy[t];
         lazy[t*2 + 1] = lazy[t*2 + 1] + lazy[t];
      }
      push[t] = false;
      lazy[t] = 0;
   }
}

//Complexity: O(n)
void build(int t, int i, int j) {
   push[t] = false;
   lazy[t] = 0;
   if (i == j) {
      //base case : leaf node information to be stored here
      seg[t] = a[i];
      return ;
   }
   int mid = (i + j) / 2;
   build(t*2, i, mid);
   build(t*2 + 1, mid + 1, j);
   seg[t] = combine(seg[2*t], seg[2*t+1]);
}

//Complexity: O(log n)
void update(int t, int i, int j, int l, int r, int x) {
   propagate(t, i, j);
   if (i > r || j < l) {
      return ;
   }
   if (l <= i && j <= r) {
      //base case : leaf node information to be stored here
      lazy[t] += x;
      push[t] = true;
      propagate(t, i, j);
      return ;
   }
   int mid = (i + j) / 2;
   update(t*2, i, mid, l, r, x);
   update(t*2 + 1, mid + 1, j, l, r, x);
   seg[t] = combine(seg[2*t], seg[2*t+1]);
}

//Complexity: O(log n)
int query(int t, int i, int j, int l, int r) {
   propagate(t, i, j);
   if (i > r || j < l) {
      //base case: result of out-of-bound query
      return 0;
   }
   if (l <= i && j <= r) {
      return seg[t];
   }
   int mid = (i + j) / 2;
   if (l <= mid) {
      if (r <= mid) {
         return query(t*2, i, mid, l, r);
      }
      else {
         int a = query(t*2, i, mid, l, r);
         int b = query(t*2 + 1,  mid + 1, j, l, r);
         return combine(a, b);
      }
   }
   else {
      return query(t*2 + 1,  mid + 1, j, l, r);
   }
}

int32_t main(){_
   
   cin>>n>>d>>maxHealth;

   for (int i = 0; i < n; ++i)
   {
      int x, h;
      cin >> x >> h;
      X.push_back({x, h});
   }

   X.push_back({-inf, -inf});
   sort(X.begin(), X.end());

   build(1, 1, n);

   for (int i = 1; i <= n; ++i)
   {
      update(1, 1, n, i, i, X[i][1]);
   }

   int ans = 0;
   for (int i = 1; i <= n; ++i)
   {
      int curr = query(1, 1, n, i, i);
      if(curr < 0)
         continue;
      int x = X[i][0]; 
      int nxt = x + 2*d;
      vector<int> tt = {nxt, inf};
      auto it = upper_bound(X.begin(), X.end(), tt);
      --it;
      int idx = it - X.begin();
      ans += (curr + maxHealth - 1) / maxHealth;
      int vals = ((curr + maxHealth - 1) / maxHealth) * maxHealth; 
      update(1, 1, n, i, idx, -vals);
   }
   
   cout<<ans;

   return 0;
}

Measured memory_bytes: 24108