#include <bits/stdc++.h>
using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

#define fastio() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define test() int t;cin>>t;for(int test=1;test<=t;test++)
#define pb push_back
#define nl cout<<"\n"
#define F first
#define S second
#define all(x) x.begin(),x.end()

template<class C> void min_self( C &a, C b ){ a = min(a,b); }
template<class C> void max_self( C &a, C b ){ a = max(a,b); }

const ll MOD = 1000000007;
ll mod( ll n, ll m=MOD ){ n%=m,n+=m,n%=m;return n; }

const int MAXN = 1e5+5;
const int LOGN = 21;
const ll INF = 1e14;
int dx[] = {1,0,-1,0};
int dy[] = {0,1,0,-1};


class SegmentTree
{
public:
    int N, sz;
    vector<ll>tree, lazy;
    vector<bool>marked;
    SegmentTree( vector<ll>&a )
    {
        N = a.size();
        sz = 4*N;
        tree.resize(sz);
        lazy.resize(sz);
        marked.resize(sz);
        build(0,0,N-1,a);
    }
    ll merge( ll x, ll y )
    {
        // Fill merge function
        return x + y;
    }
    void build( int v, int l, int r, vector<ll>&a )
    {
        if( l == r )
        {
            tree[v] = a[l];
            return;
        }
        int m = l + (r-l)/2;
        build( 2*v+1, l, m, a );
        build( 2*v+2, m+1, r, a );
        tree[v] = merge( tree[2*v+1], tree[2*v+2] );
    }
    void update( int v, int l, int r, int p, ll val )
    {
        if( p < l || p > r ) return;
        if( l == r )
        {
            tree[v] = val;
            return;
        }
        int m = l + (r-l)/2;
        update( 2*v+1, l, m, p, val );
        update( 2*v+2, m+1, r, p, val );
        tree[v] = merge( tree[2*v+1], tree[2*v+2] );
    }
    void push( int v )
    {
        if( marked[v] )
        {
            int lch = 2*v+1, rch = 2*v+2;
            tree[lch] += lazy[v];
            lazy[lch] += lazy[v];

            tree[rch] += lazy[v];
            lazy[rch] += lazy[v];

            lazy[v] = 0;
            
            marked[lch] = marked[rch] = true;
            marked[v] = false;
        }
    }
    void range( int v, int l, int r, int ql, int qr, ll dec )
    {
        if( ql > qr )
            return;
        if( ql == l && qr == r )
        {
            tree[v] -= dec;
            lazy[v] -= dec;
            marked[v] = true;
            return;
        }
        push(v);
        int m = l + (r-l)/2;
        range(2*v+1, l, m, ql, min(qr,m), dec);
        range(2*v+2, m+1, r, max(ql,m+1), qr, dec);
        tree[v] = merge( tree[2*v+1], tree[2*v+2] );
    }
    ll query( int v, int l, int r, int ql, int qr )
    {
        if( qr < l || ql > r )
            return 0;
        if( ql <= l && r <= qr )
            return tree[v];
        push(v);
        int m = l + (r-l)/2;
        return merge( query(2*v+1,l,m,ql,qr), query(2*v+2,m+1,r,ql,qr) );
    }
    ll get( int l, int r )
    {
        return query(0,0,N-1,l,r);
    }
    void decrease( int l, int r, ll dec )
    {
        range(0,0,N-1,l,r,dec);
    }
};


int main() 
{
    fastio();

    int n;
    ll d,a;
    cin>>n>>d>>a;
    vector<pll>v;
    for(int i=0;i<n;i++)
    {
        ll x,h;
        cin>>x>>h;
        v.pb({x,h});
    }
    sort(all(v));

    vector<ll>hh(n);
    for(int i=0;i<n;i++)
    {
        hh[i] = v[i].S;
    }

    SegmentTree st(hh);

    int l = 0, r = -1;
    ll ans = 0;
    while( l < n )
    {
        if( r+1 < n && v[r+1].F - v[l].F <= 2*d )
        {
            r++;
        }
        else
        {
            ll now = st.get(l,l);
            ll dec = ( now + a - 1 ) / a ;
            if( now <= 0 )
            {
                l++;
            }
            else
            {
                ans += dec;
                st.decrease(l,r,a*dec);
            }
        }
    }
    cout<<ans,nl;

    cerr << "\nTime elapsed: " << 1000 * clock() / CLOCKS_PER_SEC << "ms\n";
    return 0;
}

Measured memory_bytes: 18156