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 Java8 (OpenJDK 1.8.0) (judge verdict: Runtime Error)

import java.util.*;
import java.util.Map.*;
import java.util.function.*;

class LazySegmentTree<T,A>{
	/**
	 * a+0=a
	 * a+(b+c)=(a+b)+c
	 */
	public static class Monoid<T,R> implements BiFunction<T,T,R>{
		T identity;

		BiFunction<T,T,R> f;
		public Monoid(T identity,BiFunction<T,T,R> f){
			this.identity=identity;
			this.f=f;
		}
		@Override
		public R apply(T t,T u){
			return f.apply(t,u);
		}
	}

	private final T[] array;
	private final A[] lazy;
	final int size;
	private final int highestbit,len[];

	/**
	 * (v1,v2)->v
	 */
	private final Monoid<T,T> merger;
	/**
	 * (v,lazy)->v
	 */
	private final BiFunction<T,A,T> applyer;
	/**
	 * (apply,apply)->apply
	 */
	private final Monoid<A,A> unifyer;
	/**
	 * (v,length)->v
	 */
	private final BiFunction<A,Integer,A> multiplier;

	@SuppressWarnings("unchecked")
	LazySegmentTree(int size,
			Monoid<T,T> merger,
			BiFunction<T,A,T> applyer,
			Monoid<A,A> unifyer,
			BiFunction<A,Integer,A> multiplier){
		this.size=size;
		this.highestbit=Integer.highestOneBit(size);
		this.merger=merger;
		this.applyer=applyer;
		this.unifyer=unifyer;
		this.multiplier=multiplier;

		this.array=(T[])new Object[size*2];
		this.lazy=(A[])new Object[size*2];
		this.len=new int[size*2];

		Arrays.fill(array,merger.identity);
		Arrays.fill(lazy,unifyer.identity);
		for(int i=len.length-1;i>=0;--i)
			len[i]=i>=size?1:len[i<<1]+len[i<<1|1];
	}

	private void set(int i,A laz){
		array[i]=applyer.apply(array[i],
				multiplier.apply(laz,len[i]));
		if(i<size)
			lazy[i]=unifyer.apply(lazy[i],laz);
	}

	/**
	 * [l, r)
	 */
	void apply(int l,int r,A value){
		int l0=l+=size,r0=r+=size;
		for(;l<r;l>>=1,r>>=1){
			if((l&1)>0) set(l++,value);
			if((r&1)>0) set(--r,value);
		}
		updateParents(l0);
		updateParents(r0-1);
	}
	private void updateParents(int p){
		while(p>1){
			p>>=1;
			array[p]=applyer.apply(
					merger.apply(array[p<<1],array[p<<1|1]),
					multiplier.apply(lazy[p],len[p]));
		}
	}

	/**
	 * [l, r)
	 */
	T query(int l,int r){
		T res=merger.identity;
		spreadLazy(l+=size);
		spreadLazy((r+=size)-1);
		for(;l<r;l>>=1,r>>=1){
			if((l&1)>0) res=merger.apply(res,array[l++]);
			if((r&1)>0) res=merger.apply(res,array[--r]);
		}
		return res;
	}
	private void spreadLazy(int p){
		for(int s=highestbit;s>0;s>>=1){
			int i=p/s;
			if(!unifyer.identity.equals(lazy[i])){
				set(i<<1,lazy[i]);
				set(i<<1|1,lazy[i]);
				lazy[i]=unifyer.identity;
			}
		}
	}
}

public class Main{
	public static void main(String[] $){
		final Scanner s=new Scanner(System.in);
		final int n=s.nextInt();
		final int d=s.nextInt();
		final int a=s.nextInt();
		int[] x=new int[n];

		LazySegmentTree<Long,Long> seg=new LazySegmentTree<>(
				n,
				new LazySegmentTree.Monoid<>(0L,Long::sum),
				Long::sum,
				new LazySegmentTree.Monoid<>(0L,Long::sum),
				(o,l)->o*l);

		TreeMap<Integer,Integer> m=new TreeMap<>();
		{
			for(int i=0;i<n;++i)
				m.put(s.nextInt(),s.nextInt());
			int i=0;
			for(Entry<Integer,Integer> e:m.entrySet()){
				x[i]=e.getKey();
				seg.apply(i,i+1,e.getValue().longValue());
				e.setValue(i++);
			}
		}

		long r=0;
		for(int i=0;i<n;++i){
			int j=m.floorEntry(x[i]+d*2).getValue();
			long v=seg.query(i,i+1);
			if(v>0){
				long t=(v+a-1)/a;
				r+=t;
				seg.apply(i,j+1,-t*a);
			}
		}
		System.out.println(r);
	}
}