#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,n) for(ll i=0;i<n;++i)
#define rep1(i,n) for(ll i=1;i<=n;++i)
#define eachdo(e,array) for(const auto& e : array)
#define upper_index(v,a) (ll)distance(v.begin(), upper_bound((v).begin(),(v).end(),a))
template<class T> bool chmin(T &a, T b){if(a>b){a=b;return true;}return false;}
const ll INF=1LL<<63-1;
const ll MOD=1e9+7;

struct SegmentTree{
private:
    ll unit=0;
    ll op(ll a,ll b){return a+b;}
    ll n;
    vector<ll> node;

public:
    // initialize
    SegmentTree(vector<ll> v){
        ll sz=(ll)v.size();
        n=1;while(n<sz) n*=2;
        node.resize(2*n-1,unit);
        for(ll i=0;i<sz;i++) node[i+n-1]=v[i];
        for(ll i=n-2;i>=0;i--) node[i]=op(node[2*i+1],node[2*i+2]);
    }

    void update(ll x,ll val){
        x+=n-1;
        node[x]+=val;
        while(x>0){
            x=(x-1)/2;
            node[x]=op(node[2*x+1],node[2*x+2]);
        }
    }

    ll query(ll a,ll b,ll k=0,ll l=0,ll r=-1){
        if (r<0) r=n;
        if (r<=a || b<=l) return unit;
        if (a<=l && r<=b) return node[k];
        ll vl = query(a,b,2*k+1,l,(l+r)/2);
        ll vr = query(a,b,2*k+2,(l+r)/2,r);
        return op(vl,vr);
    }
};

// 区間加算・区間和クエリ
struct LazySegmentTree{
private:
    ll n;
    vector<ll> node,lazy;
public:
    // initialize
    LazySegmentTree(vector<ll> v){
        ll sz=(ll)v.size();
        n=1;while(n<sz) n*=2;
        node.resize(2*n-1);
        lazy.resize(2*n-1);
        for(ll i=0;i<sz;i++) node[i+n-1]=v[i];
        for(ll i=n-2;i>=0;i--) node[i]=node[2*i+1]+node[2*i+2];
    }

    void lazyEval(ll k,ll l,ll r){
        if(lazy[k]!=0){
            node[k]+=lazy[k];
            // r-l==1であるとき、kはleafであるため子を参照してはいけない
            if(r-l>1){
                lazy[2*k+1]+=lazy[k]/2;
                lazy[2*k+2]+=lazy[k]/2;
            }
            lazy[k]=0;
        }
    }
    //　ノードkに適切な値を入れ、遅延情報を初期化する
    void update(ll a,ll b,ll x,ll k=0,ll l=0,ll r=-1){
        if(r<0) r=n;
        // もともと入ってた遅延情報の処理
        lazyEval(k,l,r);
        if(b<=l || r<=a) return;
        if(a<=l && r<=b){
            lazy[k]+=(r-l)*x;
            lazyEval(k,l,r);
        }
        else{
            update(a,b,x,2*k+1,l,(l+r)/2);
            update(a,b,x,2*k+2,(l+r)/2,r);
            node[k]=node[2*k+1]+node[2*k+2];
        }
    }

    ll query(ll a,ll b,ll k=0,ll l=0,ll r=-1){
        if(r<0) r=n;
        if(b<=l || r<=a) return 0; 

        lazyEval(k,l,r);
        if(a<=l && r<=b) return node[k];
        ll vl=query(a,b,2*k+1,l,(l+r)/2);
        ll vr=query(a,b,2*k+2,(l+r)/2,r);
        return vl+vr;
    }

    ll at(ll a){return query(a,a+1);}
};

int main(){
    ll N,D,A;cin>>N>>D>>A;
    vector<pair<ll,ll>> E(N);rep(i,N)cin>>E[i].first>>E[i].second;
    sort(E.begin(),E.end());
    vector<ll> locate(N);rep(i,N) locate[i]=E[i].first;
    LazySegmentTree bit(vector<ll>(N+5,0));
    ll res=0;
    rep(i,N){
        if(bit.at(i)<E[i].second){
            ll times=(E[i].second-bit.at(i)+A-1)/A;
            bit.update(i,min(N,upper_index(locate,locate[i]+2*D)),A*times);
            res+=times;
        }
    }
    cout<<res<<endl;
    return 0;
}

Measured memory_bytes: 14720