#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <list>
#include <map>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <limits>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <numeric>
#include <unordered_set>
#include <unordered_map>
#include <chrono>
#include <random>
#include <bits/stdc++.h>
 
using namespace std;
 
#define ll long long
#define PI 3.14159265358979323846
#define min(a,b) ((a<b)?(a):(b))
#define max(a,b) ((a<b)?(b):(a))
#define abs(a) ((a>0)?a:-(a))
#define pii pair<int,int>
#define pll pair<long long,long long>

const double eps = (double)1e-6;
const int maxn = 2e5+600;
const ll mod = 1e9+7;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

pll p[maxn];
ll arr[maxn];  //原array
ll tr[4*maxn];  //线段树array
ll lazy[4*maxn];  //lazy tag Array

/* 这里推荐将所有array的index都设定为从1开始！ */
/* 注意调用时，用的都是maxn-2! (其中如果数据范围是2e5, 则 maxn = 2e5+5) */

/* 保持tr[i]的值 */
void push_up(ll i) {
    tr[i] = tr[i<<1] + tr[(i<<1)+1];
}

/* 将lazy tag向下传递，传递时也更新tr[]的值 */
void push_down(ll i, ll l, ll r) {
    ll mid = l + ((r - l) >> 1);

    lazy[i<<1] += lazy[i];
    lazy[(i<<1)+1] += lazy[i];
    
    /* 根据区间长度更新tr[]的值 */
    tr[i<<1] += lazy[i] * (mid - l + 1);
    tr[(i<<1)+1] += lazy[i] * (r - mid);

    lazy[i] = 0;
}


/* i是当前的在tr中的index, [l,r]是当前Node覆盖的范围 */
/* 调用: build(1, 1, maxn-2); */
void build(ll i, ll l, ll r) {
    if (l == r) {
        tr[i] = arr[l];
        return;
    }

    ll mid = l + ((r - l) >> 1);
    build(i<<1, l, mid);
    build((i<<1)+1, mid+1, r);
    push_up(i);
}

/* 查找arr[qL, qR]之间的和 */
/* 调用: query(1, 1, maxn-2, qL, qR); */
ll query(ll i, ll l, ll r, ll qL, ll qR) {
    if (qL <= l && qR >= r) {
        return tr[i];
    }

    ll mid = l + ((r - l) >> 1);
    ll result = 0;
    /* 先传递lazy tag */
    push_down(i, l, r);

    /* 判断是否需要query左边 */
    if (qL <= mid) {
        result += query(i<<1, l, mid, qL, qR);
    }
    /* 判断是否需要query右边 */
    if (qR > mid) {
        result += query((i<<1)+1, mid+1, r, qL, qR);
    }
    push_up(i);

    return result;
}

/* 将arr[qL, qR]之间的所有元素增加val */
/* 调用: update(1, val, 1, maxn-2, qL, qR); */
void update(ll i, ll val, ll l, ll r, ll qL, ll qR) {
    if (qL <= l && qR >= r) {
        tr[i] += val * (r - l + 1);
        lazy[i] += val;
        return;
    }

    ll mid = l + ((r - l) >> 1);
    
    /* 先传递lazy tag, 再更新 */
    push_down(i, l, r);
    /* 更新与query一样 */
    if (qL <= mid) {
        update(i<<1, val, l, mid, qL, qR);
    }
    if (qR > mid) {
        update((i<<1)+1, val, mid+1, r, qL, qR);
    }
    push_up(i);
}

bool cmp(ll se, pll fi) {
    return se <= fi.first;
}

int main() {
 
    ios::sync_with_stdio(false);
    cin.tie(0);

    ll n;
    ll d, damage; cin >> n >> d >> damage;

    ll x,h;
    for (ll i = 1; i <= n; i++) {
        cin >> x >> h;
        p[i] = {x,h/damage};
        if (h % damage) p[i].second++;
    }

    sort(p+1, p+n+1);  //x从左到右
    for (ll i = 1; i <= n; i++) arr[i] = p[i].second;
    build(1,1,maxn-2);
    ll ans = 0;
    for (ll i = 1; i <= n; i++) {
        ll req;
        if ((req = query(1,1,maxn-2,i,i)) <= 0) continue;
        ans += req;
        ll r = upper_bound(p+1,p+n+1,p[i].first+2*d+1,cmp) - p - 1;
        update(1, -req, 1, maxn-2, i, r);
    }
    cout << ans << endl;
}



Measured memory_bytes: 17536