#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mp make_pair
#define pb push_back
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
//0-indexedで用いる (実装は1-indexedの配列だけど
//set(k,x) k番目の要素にxを代入する
//build() (代入で作った場合)セグメント木を構築するのに必要
//query(a,b) 区間[a,b)に対して二項演算した結果を返す
//update(k,x) k(0-indexed)番目の要素をxに変更する 
//operator[k] k(0-indexed)番目の要素を返す

template< typename Monoid, typename OperatorMonoid = Monoid >
struct LazySegmentTree {
  using F = function< Monoid(Monoid, Monoid) >;
  using G = function< Monoid(Monoid, OperatorMonoid, int) >;
  using H = function< OperatorMonoid(OperatorMonoid, OperatorMonoid) >;

  int sz;
  vector< Monoid > data;
  vector< OperatorMonoid > lazy;
  const F f;
  const G g;
  const H h;
  const Monoid M1;
  const OperatorMonoid OM0;


  LazySegmentTree(int n, const F f, const G g, const H h,
                  const Monoid &M1, const OperatorMonoid OM0)
     : f(f), g(g), h(h), M1(M1), OM0(OM0) {
    sz = 1;
    while(sz < n) sz <<= 1;
    data.assign(2 * sz, M1);
    lazy.assign(2 * sz, OM0);
  }

  void set(int k, const Monoid &x) {
    data[k + sz] = x;
  }

  void build() {
    for(int k = sz - 1; k > 0; k--) {
      data[k] = f(data[2 * k + 0], data[2 * k + 1]);
    }
  }

  void propagate(int k, int len) {
    if(lazy[k] != OM0) {
      if(k < sz) {
        lazy[2 * k + 0] = h(lazy[2 * k + 0], lazy[k]);
        lazy[2 * k + 1] = h(lazy[2 * k + 1], lazy[k]);
      }
      data[k] = g(data[k], lazy[k], len);
      lazy[k] = OM0;
    }
  }

  Monoid update(int a, int b, const OperatorMonoid &x, int k, int l, int r) {
    propagate(k, r - l);
    if(r <= a || b <= l) {
      return data[k];
    } else if(a <= l && r <= b) {
      lazy[k] = h(lazy[k], x);
      propagate(k, r - l);
      return data[k];
    } else {
      return data[k] = f(update(a, b, x, 2 * k + 0, l, (l + r) >> 1),
                         update(a, b, x, 2 * k + 1, (l + r) >> 1, r));
    }
  }

  Monoid update(int a, int b, const OperatorMonoid &x) {
    return update(a, b, x, 1, 0, sz);
  }


  Monoid query(int a, int b, int k, int l, int r) {
    propagate(k, r - l);
    if(r <= a || b <= l) {
      return M1;
    } else if(a <= l && r <= b) {
      return data[k];
    } else {
      return f(query(a, b, 2 * k + 0, l, (l + r) >> 1),
               query(a, b, 2 * k + 1, (l + r) >> 1, r));
    }
  }

  Monoid query(int a, int b) {
    return query(a, b, 1, 0, sz);
  }

  Monoid operator[](const int &k) {
    return query(k, k + 1);
  }
};

int main() {
  //  SegmentTree(n,f,g,h,M1,OM0):= サイズ n の初期化。ここで f は2つの区間の要素をマージする二項演算, g は要素と作用素をマージする二項演算(第三引数は対応する区間の長さ), h は作用素同士をマージする二項演算, M1 はモノイドの単位元, OM0 は作用素の単位元である。
  //f 二つの区間の連結方法
  //g 遅延させた作用を区間に作用させるときの方法
  //h 作用同士を結合させる方法
  //区間はM1,作用素はOM0で初期化される。区間がM1、作用素がOM0の時とき更新は行われない
  
  //区間加算 区間和 (区間和が要素だから、要素に区間加算を作用させるには+b*lenが必要 min or maxなら+b
  
  // PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_G 
  // S--, T--使う
  
  //区間加算 区間最小値
  // PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_H&lang=ja
  // LazySegmentTree< ll > seg(N, [](ll a, ll b) { return min(a,b); }, [](ll a, ll b, ll len) { return a+b; }, [](ll a, ll b) { return a+b; }, LLONG_MAX, 0);
  // rep(i,N) seg.set(i,0);
  // seg.build();
  //区間更新 区間和
  // PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_I  
  // 単位元の状態では更新されないので、LLONG_MAXの部分は範囲外の値に

  ll n,d,a;
  cin >> n >> d >> a;
  LazySegmentTree< ll > seg(n, [](ll a, ll b) { return (a+b); }, [](ll a, ll b, ll len) { return a+b*len; }, [](ll a, ll b) { return a+b; }, 0, 0);
  vector<pair<ll, ll>> ene(n);
  rep(i,n){
    ll x,h;
    cin >> x >> h;
    ene[i] = {x,h};
  }
  sort(ene.begin(),ene.end());
  rep(i,n){
    seg.set(i, ene[i].second);
  }
  seg.build();
  ll ans=0;
  ll cu_x,r_ind;  
  r_ind = 0;
  rep(i,n){
    cu_x = ene[i].first;
    while(ene[r_ind+1].first<=cu_x+2*d){
      if(r_ind==n-1) break;
      r_ind++;
      if(r_ind==n-1) break;
    }
    //    cout << r_ind << endl;
    ll hel = seg.query(i,i+1);
    if(hel<=0) continue;
    //    cout <<"i health totbakuha "<<i << " " <<  hel  <<" " << ans << endl;
    ll kai =0;
    if(hel/a * a == hel) kai = hel/a;
    else kai = hel/a + 1;
    ll minus = kai * a;
    seg.update(i,r_ind+1,-minus);
    ans += kai;
  }
  cout << ans << endl;
  return 0;
}


Measured memory_bytes: 11520