Buggy python submission (verdict: Time Limit Exceeded):
import bisect


class BinaryIndexTree:  # 1-indexed
    def __init__(self, n):
        self.size = n
        self.tree = [0] * (n + 1)

    def sum(self, i):
        s = 0
        while i > 0:
            s += self.tree[i]
            i -= i & -i
        return s

    def add(self, i, x):
        while i <= self.size:
            self.tree[i] += x
            i += i & -i


N, D, A = map(int, input().split())
XH = [list(map(int, input().split())) for _ in range(N)]
XH.sort()
X, H = zip(*XH)

bit = BinaryIndexTree(N)

ans = 0
for i in range(N):
    x = X[i]
    h = H[i]
    h -= bit.sum(i+1)
    if h <= 0:
        continue
    atk = (h + A - 1) // A
    ans += atk
    damage = atk * A
    bit.add(i+1, damage)
    pos = bisect.bisect_right(X, x+2*D)
    pos = min(N + 1, pos)
    bit.add(pos+1, -damage)

print(ans)


Fixed submission:
from collections import deque
N, D, A = map(int, input().split())
XH = [list(map(int, input().split())) for _ in range(N)]
XH.sort()

que = deque([])
ans = 0
total = 0

for i in range(N):
    x, h = XH[i]
    if h <= 0:
        continue
    while que and XH[i][0] > que[0][0]:
        _, tmp = que.popleft()
        total -= tmp

    h -= total
    if h > 0:
        atk = (h + A - 1) // A
        damage = atk * A
        ans += atk
        total += damage
        que.append((x+2*D, damage))

print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
N, D, A = map(int, input().split())
XH = [list(map(int, input().split())) for _ in range(N)]
XH.sort(key=lambda x: x[0])

ans = 0

for i in range(N):
    if XH[i][1] <= 0:
        continue
    explode = (XH[i][1] + A - 1) // A
    for j in range(i, N):
        if XH[j][0] <= XH[i][0]+2*D:
            XH[j][1] -= explode*A
        else:
            break

    ans += explode

print(ans)


Fixed submission:
from collections import deque
N, D, A = map(int, input().split())
XH = [list(map(int, input().split())) for _ in range(N)]
XH.sort()

que = deque([])
ans = 0
total = 0

for i in range(N):
    x, h = XH[i]
    if h <= 0:
        continue
    while que and XH[i][0] > que[0][0]:
        _, tmp = que.popleft()
        total -= tmp

    h -= total
    if h > 0:
        atk = (h + A - 1) // A
        damage = atk * A
        ans += atk
        total += damage
        que.append((x+2*D, damage))

print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import numpy as np
N, D, A = map(int, input().split())
XH = [list(map(int, input().split())) for _ in range(N)]
XH.sort(key=lambda x: x[0])
XH = np.array(XH).astype(np.int64)

X = XH[:, 0]
H = XH[:, 1]

ans = 0

for i in range(N):
    if H[i] <= 0:
        continue
    pos = X[i]
    explode = (H[i] + A - 1) // A
    ex_range = (X >= pos) & (X <= pos+2*D)
    H[ex_range] -= explode*A

    ans += explode

print(ans)


Fixed submission:
from collections import deque
N, D, A = map(int, input().split())
XH = [list(map(int, input().split())) for _ in range(N)]
XH.sort()

que = deque([])
ans = 0
total = 0

for i in range(N):
    x, h = XH[i]
    if h <= 0:
        continue
    while que and XH[i][0] > que[0][0]:
        _, tmp = que.popleft()
        total -= tmp

    h -= total
    if h > 0:
        atk = (h + A - 1) // A
        damage = atk * A
        ans += atk
        total += damage
        que.append((x+2*D, damage))

print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
N, D, A = map(int, input().split())
XH = [list(map(int, input().split())) for _ in range(N)]
XH.sort(key=lambda x: x[0])

ans = 0
i = 0
while True:
    alive = True
    for j in range(i, N):
        x, h = XH[j]
        if h <= 0:
            continue
        i = j
        pos = x
        explode = (h + A - 1) // A
        break
    else:
        alive = False
        break

    if not alive:
        break

    for j in range(i, N):
        x, _ = XH[j]
        if x <= pos+2 * D:
            XH[j][1] -= explode * A
        else:
            break
    ans += explode

print(ans)


Fixed submission:
from collections import deque
N, D, A = map(int, input().split())
XH = [list(map(int, input().split())) for _ in range(N)]
XH.sort()

que = deque([])
ans = 0
total = 0

for i in range(N):
    x, h = XH[i]
    if h <= 0:
        continue
    while que and XH[i][0] > que[0][0]:
        _, tmp = que.popleft()
        total -= tmp

    h -= total
    if h > 0:
        atk = (h + A - 1) // A
        damage = atk * A
        ans += atk
        total += damage
        que.append((x+2*D, damage))

print(ans)