Buggy python submission (verdict: Time Limit Exceeded):
#!/usr/bin/env python3
import sys
import math


def solve(N: int, D: int, A: int, X: "List[int]", H: "List[int]"):
    M = sorted([(X[i], H[i]) for i in range(N)])
    DD = 2*D
    result = 0
    next = 0
    while next <= N-1:
        hasNonZero = False
        breaken = False
        left = M[next]
        attackCount = math.ceil(left[1]/A)
        damage = attackCount*A
        result += attackCount
        # print(f"max X:{left[0]+DD}")
        for i in range(next, N):
            if M[i][0] <= left[0]+DD:
                M[i] = (M[i][0], max(0, M[i][1]-damage))
                if not hasNonZero and M[i][1] != 0:
                    hasNonZero = True
                    breaken = True
                    next = i
            else:
                if not hasNonZero:
                    next = i
                breaken = True
                break
        if not breaken:
            next = N
        # print(f"next:{next}")
        # print(M)
    print(result)
    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    D = int(next(tokens))  # type: int
    A = int(next(tokens))  # type: int
    X = [int()] * (N)  # type: "List[int]"
    H = [int()] * (N)  # type: "List[int]"
    for i in range(N):
        X[i] = int(next(tokens))
        H[i] = int(next(tokens))
    solve(N, D, A, X, H)


if __name__ == '__main__':
    main()


Fixed submission:
#!/usr/bin/env python3
import sys
import math
from collections import deque


def solve(N: int, D: int, A: int, X: "List[int]", H: "List[int]"):
    M = sorted([(X[i], H[i]) for i in range(N)])
    DD = 2*D
    result = 0
    revert = deque()
    currentDamage = 0
    for m in M:
        while len(revert) > 0 and revert[0][0] < m[0]:
            currentDamage -= revert[0][1]
            revert.popleft()
        nextDamage = max(0, m[1] - currentDamage)
        needAttack = math.ceil(nextDamage/A)
        currentDamage += needAttack * A
        result += needAttack
        if needAttack > 0:
            revert.append((m[0]+2*D, needAttack*A))
    print(result)
    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    D = int(next(tokens))  # type: int
    A = int(next(tokens))  # type: int
    X = [int()] * (N)  # type: "List[int]"
    H = [int()] * (N)  # type: "List[int]"
    for i in range(N):
        X[i] = int(next(tokens))
        H[i] = int(next(tokens))
    solve(N, D, A, X, H)


if __name__ == '__main__':
    main()

Buggy python submission (verdict: Time Limit Exceeded):
#!/usr/bin/env python3
import sys
import math


def solve(N: int, D: int, A: int, X: "List[int]", H: "List[int]"):
    M = sorted([(X[i], H[i]) for i in range(N)])
    DD = 2*D
    result = 0
    next = 0
    while next <= N-1:
        hasNonZero = False
        breaken = False
        left = M[next]
        attackCount = math.ceil(left[1]/A)
        damage = attackCount*A
        result += attackCount
        # print(f"max X:{left[0]+DD}")
        for i in range(next, N):
            if M[i][0] <= left[0]+DD:
                M[i] = (M[i][0], max(0, M[i][1]-damage))
                if not hasNonZero and M[i][1] != 0:
                    hasNonZero = True
                    breaken = True
                    next = i
            else:
                if not hasNonZero:
                    next = i
                breaken = True
                break
        if not breaken:
            next = N
        # print(f"next:{next}")
        # print(M)
    print(result)
    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    D = int(next(tokens))  # type: int
    A = int(next(tokens))  # type: int
    X = [int()] * (N)  # type: "List[int]"
    H = [int()] * (N)  # type: "List[int]"
    for i in range(N):
        X[i] = int(next(tokens))
        H[i] = int(next(tokens))
    solve(N, D, A, X, H)


if __name__ == '__main__':
    main()


Fixed submission:
#!/usr/bin/env python3
import sys
import math
from collections import deque


def solve(N: int, D: int, A: int, X: "List[int]", H: "List[int]"):
    M = sorted([(X[i], H[i]) for i in range(N)])
    DD = 2*D
    result = 0
    revert = deque()
    currentDamage = 0
    for m in M:
        while len(revert) > 0 and revert[0][0] < m[0]:
            currentDamage -= revert[0][1]
            revert.popleft()
        nextDamage = max(0, m[1] - currentDamage)
        needAttack = math.ceil(nextDamage/A)
        currentDamage += needAttack * A
        result += needAttack
        if needAttack > 0:
            revert.append((m[0]+2*D, needAttack*A))
    print(result)
    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    D = int(next(tokens))  # type: int
    A = int(next(tokens))  # type: int
    X = [int()] * (N)  # type: "List[int]"
    H = [int()] * (N)  # type: "List[int]"
    for i in range(N):
        X[i] = int(next(tokens))
        H[i] = int(next(tokens))
    solve(N, D, A, X, H)


if __name__ == '__main__':
    main()