#include <bits/stdc++.h>

using namespace std;

#define INF 100000000
#define YJ 1145141919
#define INF_INT_MAX 2147483647
#define INF_LL 9223372036854775
#define INF_LL_MAX 9223372036854775807
#define EPS 1e-10
#define MOD 1000000007
#define MOD9 998244353
#define Pi acos(-1)
#define LL long long
#define ULL unsigned long long
#define LD long double

#define int long long

using II = pair<int, int>;

int gcd(int a, int b) { return b != 0 ? gcd(b, a % b) : a; }
int lcm(int a, int b) { return a * b / gcd(a, b); }
int extgcd(int a, int b, int &x, int &y) { int g = a; x = 1; y = 0; if (b != 0) g = extgcd(b, a % b, y, x), y -= (a / b) * x; return g; }

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(a)  begin((a)), end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define MP make_pair
#define SZ(a) int((a).size())

const int MAX_N = 200005;
int N, D, A;
struct Mons {
  int X, H;
  void input()
  {
    cin >> X >> H;
  }
  bool operator < (const Mons& m) const {
    return X < m.X;
  }
};
Mons M[MAX_N];

class RangeNode {
public:
  RangeNode() {
    init();
  }

  void init() {
    delay = delayFlag = 0;
    val = 0;
  }

  //クエリ処理
  static int evaluateQuery(int p1, int p2) 
  {
    return max(p1, p2);
  }

  //range処理
  void evaluateRange(int range) 
  {
    val += delay*range;
  }

  //delay処理
  void evaluateDelay(int d)
  {
    delay += d;
  }

  //単位元(クエリ処理)
  static int unit()
  {
    return 0;
  }

  int val;
  int delay;
  bool delayFlag;

private:

};

template<class T, int Size>
class RangeSegmentTree {
public:
  RangeSegmentTree() 
  {
    init();
  }

  void init()
  {
    n = 1;
    while(n < Size) n *= 2;
    node.clear(); node.resize(2*n);
  }

  void evaluateRangeNode(int k, int l, int r)
  {
    if(node[k].delayFlag) {
      node[k].evaluateRange(r-l);
      if(r-l>1) {
        node[2*k+1].evaluateDelay(node[k].delay);
        node[2*k+2].evaluateDelay(node[k].delay);
        node[2*k+1].delayFlag = node[2*k+2].delayFlag = true;
      }
      node[k].delayFlag = false;
      node[k].delay = 0;
    }
  }

  void updateRange(int l, int r, int v)
  {
    _updateRange(l,r,v,0,0,n);
  }

  int query(int l, int r)
  {
    return _query(l,r,0,0,n);
  }

private:
  vector<T> node;
  int n;

  void _updateRange(int l, int r, int v, int k, int a, int b)
  {
    evaluateRangeNode(k,a,b);

    if(b <= l || r <= a) return;
    else if(l <= a && b <= r) {
      node[k].evaluateDelay(v);
      node[k].delayFlag = true;
      evaluateRangeNode(k,a,b);
      return;
    } else {
      int mid = (a+b)/2;
      _updateRange(l,r,v,2*k+1,a,mid);
      _updateRange(l,r,v,2*k+2,mid,b);
      node[k].val = RangeNode::evaluateQuery(node[2*k+1].val, node[2*k+2].val);
      return;
    }
  }

  int _query(int l, int r, int k, int a, int b)
  {
    evaluateRangeNode(k,a,b);
    
    if(b <= l || r <= a) return RangeNode::unit();
    else if(l <= a && b <= r) {
      return node[k].val;
    } else {
      int mid = (a+b)/2;
      int vl = _query(l,r,2*k+1,a,mid);
      int vr = _query(l,r,2*k+2,mid,b);
      return RangeNode::evaluateQuery(vl,vr);
    }
  }
};

RangeSegmentTree<RangeNode, MAX_N> rst;

signed main()
{
  cin >> N >> D >> A;
  REP(n,N) {
    M[n].input();
  }

  sort(M, M+N);

  REP(n,N) {
    rst.updateRange(n,n+1,M[n].H);
  }

  int ans = 0;
  int r = 0;
  REP(n,N) {
    r = max(r, n);
    int h = rst.query(n,n+1);
    if(h < 0) {
      continue;
    }

    int tmp = h/A + (h%A > 0 ? 1 : 0);
    ans += tmp;

    while(r < N && M[r].X - M[n].X <= 2*D) {
      r++;
    }

    rst.updateRange(n,r,-tmp*A);
  }

  cout << ans << endl;

  return 0;
}


Measured memory_bytes: 15616