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# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using static Exter;
using System.Linq;
using System.Numerics;
#if DEBUG
#else
using console = System.Console;
#endif

public class App
{
    public static void Main(string[] args)
    {
        int n,d,a;
        {
            var r = readarr;
            n = r[0];
            d = r[1];
            a = r[2];
        }
        
        var x = new Point[n];
        for(int i = 0;i<n;i++)
        {
            var r = readarr;
            x[i] = new Point(r[0],(r[1]-1)/a+1);
        }
        Queue<Point> y = new Queue<Point>();
        
        foreach(var v in x.OrderBy(v=>v.x))
        {
            y.Enqueue(v);
        }
        long c = 0;
        Queue<Point> q = new Queue<Point>();
        long vsum = 0;
        while(y.Count > 0)
        {
            while(q.Count > 0 && q.Peek().x + 2 * d < y.Peek().x)
                vsum -= q.Dequeue().y;
            if(vsum < y.Peek().y)
            {
                c += y.Peek().y - vsum;
                q.Enqueue(new Point(y.Peek().x,y.Peek().y - vsum));
                vsum += y.Peek().y - vsum;
            }
            y.Dequeue();
        }
        cout = c;
    }
    public string[] SnRead(int n)
    {
        var v = new string[n];
        for(int i = 0;i<n;i++)
            v[i] = console.ReadLine();
        return v;
    }
    public char[,] RectCharRead(int h,int w)
    {
        var v = new char[h,w];
        for(int i = 0;i < h;i++)
        {
            var s = console.ReadLine();
            for(int j = 0;j < w;j++)
            {
                v[i,j] = s[j];
            }
        }
        return v;
    }
    public bool[,] RectCharToBool(int h,int w)
    {
        var v = new bool[h,w];
        for(int i = 0;i < h;i++)
        {
            var s = console.ReadLine();
            for(int j = 0;j < w;j++)
            {
                v[i,j] = s[j] == '.';
            }
        }
        return v;
    }
    public class BiasedArray<Type>
    {
        private Type[] ContainedValue;
        public bool ReturnDefaultIfOutOfRange = true;
        public bool IgnoreSetIfOutOfRange = true;
        public Type DefaultValue = default(Type);
        public int Length;
        BiasedArray(int length)
        {
            Length = length;
            ContainedValue = new Type[length];
        }
        public bool IsWithinRange(int x)=>0<=x&&x<Length;
        public Type this[int x]
        {
            get
            {
                if(IsWithinRange(x))
                    return ContainedValue[x];
                else if(ReturnDefaultIfOutOfRange)
                    return DefaultValue;
                else
                    throw new IndexOutOfRangeException();
            }
            set
            {
                if(IsWithinRange(x))
                    ContainedValue[x] = value;
                else if(!IgnoreSetIfOutOfRange)
                    throw new IndexOutOfRangeException();
            }
        }
    }
    public class BiasedArray2<Type>
    {
        private Type[,] ContainedValue;
        public bool ReturnDefaultIfOutOfRange = true;
        public bool IgnoreSetIfOutOfRange = true;
        public Type DefaultValue = default(Type);
        public int Width;
        public int Height;
        BiasedArray2(int width,int height)
        {
            Width = width;
            Height = height;
            ContainedValue = new Type[width,height];
        }
        public bool IsWithinRange(int x,int y)=>0<=x&&x<Width&&0<=y&&y<Height;
        public Type this[int x,int y]
        {
            get
            {
                if(IsWithinRange(x,y))
                    return ContainedValue[x,y];
                else if(ReturnDefaultIfOutOfRange)
                    return DefaultValue;
                else
                    throw new IndexOutOfRangeException();
            }
            set
            {
                if(IsWithinRange(x,y))
                    ContainedValue[x,y] = value;
                else if(!IgnoreSetIfOutOfRange)
                    throw new IndexOutOfRangeException();
            }
        }
    }
    public class BiasedArray3<Type>
    {
        private Type[,,] ContainedValue;
        public bool ReturnDefaultIfOutOfRange = true;
        public bool IgnoreSetIfOutOfRange = true;
        public Type DefaultValue = default(Type);
        public int Width;
        public int Depth;
        public int Height;
        BiasedArray3(int width,int depth,int height)
        {
            Width = width;
            Depth = depth;
            Height = height;
            ContainedValue = new Type[width,depth,height];
        }
        public bool IsWithinRange(int x,int y,int z)=>0<=x&&x<Width&&0<=y&&y<Depth&&0<=z&&z<Height;
        public Type this[int x,int y,int z]
        {
            get
            {
                if(IsWithinRange(x,y,z))
                    return ContainedValue[x,y,z];
                else if(ReturnDefaultIfOutOfRange)
                    return DefaultValue;
                else
                    throw new IndexOutOfRangeException();
            }
            set
            {
                if(IsWithinRange(x,y,z))
                    ContainedValue[x,y,z] = value;
                else if(!IgnoreSetIfOutOfRange)
                    throw new IndexOutOfRangeException();
            }
        }
    }
    public static long Lcm(long a, long b)=>a*b/Gcd(a,b);
    public static long Gcd(long a, long b)=>a > b ? GcdRecursive(a, b) : GcdRecursive(b, a);
    private static long GcdRecursive(long a, long b){if(b == 0) return a; return GcdRecursive(b, a % b);}
}
public class RollingHash
{
    long[] h;
    long m = 2147483647;
    int b = 524287;
    Power baser;
    public RollingHash(string s)
    {
        baser = new Power(b);
        h = new long[s.Length];
        h[0] = 0;
        for(int i = 1;i < s.Length;i++)
        {
            h[i] = (h[i-1] * b + s[i]) % m;
        }
    }
    public long Calc(int l,int r)
    {
        cout = h[r];
        cout = h[l] * baser.GetEntry(r-l-1);
        return 0;
    }
}
public class PriorityQueue<T> : IEnumerable<T> where T : IComparable
        {
            List<T> buffer = new List<T>();
            static void PushHeap(List<T> array, T elem)
            {
                int n = array.Count;
                array.Add(elem);
 
                while (n != 0)
                {
                    int i = (n - 1) / 2;
                    if (array[n].CompareTo(array[i]) < 0)
                    {
                        T tmp = array[n]; array[n] = array[i]; array[i] = tmp;
                    }
                    n = i;
                }
            }
            static void PopHeap(List<T> array)
            {
                int n = array.Count - 1;
                array[0] = array[n];
                array.RemoveAt(array.Count - 1);
 
                for (int i = 0, j; (j = 2 * i + 1) < n;)
                {
                    if ((j != n - 1) && (array[j].CompareTo(array[j + 1]) > 0))
                        j++;
                    if (array[i].CompareTo(array[j]) > 0)
                    {
                        T tmp = array[j]; array[j] = array[i]; array[i] = tmp;
                    }
                    i = j;
                }
            }
            public int Count
            {
                get
                {
                    return buffer.Count;
                }
            }
            public void Push(T elem)
            {
                PushHeap(this.buffer, elem);
            }
            public T Peek()
            {
                return buffer[0];
            }
 
            public T Pop()
            {
                T a = buffer[0];
                PopHeap(this.buffer);
                return a;
            }
            public IEnumerator<T> GetEnumerator()
            {
                var v = new List<T>(buffer);
                while(v.Count != 0)
                {
                    yield return v[0];
                    PopHeap(v);
                }
            }
            IEnumerator IEnumerable.GetEnumerator()
            {
                return this.GetEnumerator();
            }
        }
public class Power
    {
        public int Base;
        private List<long> Value = new List<long>();
        public Power(int v)
        {
            if(v==1)
                new ArgumentOutOfRangeException();
            long prev = -1;
            long g = v;
            Base = v;
            
            while(g > prev)
            {
                Value.Add(g);
                prev = g;
                g *= g;
            }
        }
        public long GetEntry(int exponent)
        {
            long s = 1;
            for(int i = 0;(1<<i)<=exponent;i++)
            {
                if((exponent & (1<<i)) != 0)
                {
                    s *= Value[i];
                }
            }
            return s;
        }
    }
public static class Exter
{
    public static IEnumerable<long> PrimeFactors(long n)
    {
        int i = 2;
        long tmp = n;

        while (i * i <= n)
        {
            if(tmp % i == 0){
                tmp /= i;
                yield return i;
            }else{
                i++;
            }
        }
        if(tmp != 1) yield return tmp;
    }
    public class LoopArray<T>
    {
        public readonly int Length;
        private T[] arr;
        public LoopArray(int Capacity)
        {
            Length = Capacity;
        }
        public LoopArray(T[] ar)
        {
            arr = new T[ar.Length];
            Array.Copy(ar,arr,ar.Length);
        }
    }
    public class Point
    {
        public Point(long cx, long cy)
        {
            x = cx;
            y = cy;
        }
        public long x;
        public long y;
    }
    public static IEnumerable<Result> ListAll<T1,T2,Result>(IEnumerable<T1> a,IEnumerable<T2> b,Func<T1,T2,Result> f)
    {
        foreach(var v in a)
        {
            foreach(var w in b)
               yield return f(v,w);
        }
    }
    public static IEnumerable<Result> ListAll<T1,T2,Result>(IEnumerable<T1> a,IEnumerable<T2> b,Func<T1,T2,Result> f,Func<T1,T2,bool> s)
    {
        foreach(var v in a)
        {
            foreach(var w in b)
               if(s(v,w)) yield return f(v,w);
        }
    }
    public static int ToInt(this long v)=>(int)v;
    public static int ToInt(this string v)=>int.Parse(v);
    public static int Max(params int[] p)=>p.Max();
    public static long Max(params long[] p)=>p.Max();
    public static int Min(params int[] p)=>p.Min();
    public static long Min(params long[] p)=>p.Min();
    public static int Gcd(int a, int b)=>a > b ? GcdRecursive(a, b) : GcdRecursive(b, a);
    private static int GcdRecursive(int a, int b)=>b == 0 ? a : GcdRecursive(b, a % b);
    public static object cout
    {
        set
        {
            console.Write(value.ToString());
            console.WriteLine();
            
        }
    }
    public static void ToCout<t>(this IEnumerable<t> v)
    {
        cout = string.Join(",",v);
    }
    public static int[] readarr
    {
        get 
        {
            preadarr = console.ReadLine().Split().Select(s=>int.Parse(s)).ToArray();
            return preadarr;
        }
    }
    public static int[] preadarr;
}


#if DEBUG
public static class console
{
    static int cursorLine = 0;
    static readonly string[] cin = System.IO.File.ReadAllLines("Input.txt");
    static public string ReadLine()
    { 
        if(cursorLine == cin.Length)
            cout = "Out";
        return cin[cursorLine++];
    }
    static public void WriteLine()
    {
        Console.WriteLine();
    }
    static public void WriteLine<T>(T input)
    {
        Console.WriteLine(input);
    }
    static public void Write<T>(T input)
    {
        Console.Write(input);
    }
    static public void WriteLine(string s,params object[] arr)
    {
        Console.WriteLine(s,arr);
    }
}
#endif