Problem:
Score : 600 points

Problem Statement

Silver Fox is fighting with N monsters.

The monsters are standing in a row, and we can assume them to be standing on a number line. The i-th monster, standing at the coordinate X_i, has the health of H_i.

Silver Fox can use bombs to attack the monsters.
Using a bomb at the coordinate x decreases the healths of all monsters between the coordinates x-D and x+D (inclusive) by A.
There is no way other than bombs to decrease the monster's health.

Silver Fox wins when all the monsters' healths become 0 or below.

Find the minimum number of bombs needed to win.

Constraints

1 \leq N \leq 2 \times 10^5

0 \leq D \leq 10^9

1 \leq A \leq 10^9

0 \leq X_i \leq 10^9

1 \leq H_i \leq 10^9

X_i are distinct.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N D A
X_1 H_1
:
X_N H_N

Output

Print the minimum number of bombs needed to win.

Sample Input 1

3 3 2
1 2
5 4
9 2

Sample Output 1

2

First, let us use a bomb at the coordinate 4 to decrease the first and second monsters' health by 2.

Then, use a bomb at the coordinate 6 to decrease the second and third monsters' health by 2.

Now, all the monsters' healths are 0.
We cannot make all the monsters' health drop to 0 or below with just one bomb.

Sample Input 2

9 4 1
1 5
2 4
3 3
4 2
5 1
6 2
7 3
8 4
9 5

Sample Output 2

5

We should use five bombs at the coordinate 5.

Sample Input 3

3 0 1
300000000 1000000000
100000000 1000000000
200000000 1000000000

Sample Output 3

3000000000

Watch out for overflow.

Solution in C++14 (Clang 3.8.0) (judge verdict: Accepted)

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <vector>

// 区間加算 & 点取得
template <typename element_t, const element_t id>
class RangeAddTree{
private:
    unsigned int size;
    std::vector<element_t> data;

    static unsigned int lsb(unsigned int x){
        #ifdef __has_builtin
            return __builtin_ctz(x);
        #else 
            unsigned int res = 32;
            if(x << 16){ x <<= 16; res -= 16; }
            if(x << 8){ x <<= 8; res -= 8; }
            if(x << 4){ x <<= 4; res -= 4; }
            if(x << 2){ x <<= 2; res -= 2; }
            return (x >> 31) ? res - 1: res;
        #endif
    }

    static unsigned int msb(unsigned int x){
        #ifdef __has_builtin
            return 31 - __builtin_clz(x);
        #else 
            unsigned int res = 0;
            if(x >> 16) { x >>= 16; res += 16; }
            if(x >> 8) { x >>= 8; res += 8; }
            if(x >> 4) { x >>= 4; res += 4; }
            if(x >> 2) { x >>= 2; res += 2; }
            return res + (x >> 1);
        #endif
    }

    inline void propagate(unsigned int idx){
        // if(idx == 0) return;
        const unsigned int boundary = lsb(idx);
        for(unsigned int i = msb(idx); i > boundary; --i){
            unsigned j = idx >> i;
            data[j << 1] += data[j]; data[(j << 1) | 1U] += data[j];
            data[j] = id;
        }
    }

    void initialize(const std::vector<element_t>& A){
        const unsigned int n = A.size();
        size = 1; while(size < n) size <<= 1;
        data.assign(size << 1, id);
        for(unsigned int i = 0, j = size; i < n; ++i, ++j) data[j] = A[i];
    }
    template <class InputIterator>
    void initialize(const InputIterator first, const InputIterator last){
        const unsigned int n = last - first;
        size = 1; while(size < n) size <<= 1;
        data.assign(size << 1, id);
        InputIterator itr = first;
        for(unsigned int i = size; itr != last; ++i, ++itr) data[i] = *itr;
    }
public:
    // コンストラクタ
    RangeAddTree(const unsigned int n){
        size = 1; while(size < n) size <<= 1;
        data.assign(size << 1, id);
    }
    RangeAddTree(const std::vector<element_t>& A){ initialize(A); }
    template <class InputIterator>
    RangeAddTree(const InputIterator first, const InputIterator last){
        initialize(first, last);
    }

    // 区間更新 : 半開区間[l, r) に値 val を加える (0-indexed)  | 計算量O(logN)
    inline void update(unsigned int l, unsigned int r, const element_t& val){
        if(l >= r) return;
        propagate(l += size); propagate((r += size) - 1);
        while(l < r){
            if(l & 1U) data[l++] += val; l >>= 1;
            if(r & 1U) data[--r] += val; r >>= 1;
        }
    }
    // 点取得 : idx番目の値を取得 (0-indexed) | 計算量 O(logN)
    inline element_t operator [](unsigned int idx) const {
        element_t res = data[idx += size];
        while(idx >>= 1) res += data[idx];
        return res;
    }
    inline element_t at(unsigned int idx) const {
        assert(0 <= idx and idx < size);
        return this[idx];
    }
};


int main(void){
    unsigned int n, d; int a; scanf("%u%u%d", &n, &d, &a); d <<= 1;
    std::vector<std::pair<unsigned int, unsigned int>> A(n);
    for(unsigned int i = 0; i < n; ++i) scanf("%u%u", &A[i].first, &A[i].second);
    std::sort(A.begin(), A.end());
    std::vector<unsigned int> X(n);
    for(unsigned int i = 0; i < n; ++i) X[i] = A[i].second;
    RangeAddTree<long long int, 0> RAQ(X.begin(), X.end());
    
    unsigned long long int res = 0;
    for(unsigned int l = 0, r = 0; l < n; ++l){
        long long int val = RAQ[l]; if(val <= 0) continue;
        long long int cnt = (val - 1) / a + 1; res += cnt;
        const unsigned int boundary = A[l].first + d;
        while(r < n and A[r].first <= boundary) ++r;
        RAQ.update(l, r, -a * cnt);
    }
    printf("%llu\n", res);
    return 0;
}