Buggy python submission (verdict: Runtime Error):
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
import heapq

N, D, A = map(int, readline().split())
m = map(int,read().split())
XH = list(zip(m,m))
heapq.heapify(XH)
width = 2*D

ans = 0
while len(XH) != 0:
  xh_min = heapq.heappop(XH)
  # left + D の位置で攻撃する
  left = xh_min[0]
  right = left + width
  nAttack = (xh_min[1] + A - 1) // A
  damage = nAttack * A
    
  target = []
  while len(XH) != 0:
    xh = heapq.heappop(XH)
    if xh[0] <= right:
      if xh[1] > damage:
        target.append(xh)
    else:
      heapq.heappush(XH, xh)
      break
  if len(XH) == 0:
    maxH = max(xh_min[1], target[-1][1])
    nAttack = (maxH + A - 1) // A
    ans += nAttack
  else:
    ans += nAttack
    for t in target:
      heapq.heappush(XH, (t[0], t[1] - damage))
  
print(ans)


Fixed submission:
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
import heapq

N, D, A = map(int, readline().split())
m = map(int,read().split())
XH = list(zip(m,m))
heapq.heapify(XH)
width = 2*D

ans = 0
while len(XH) != 0:
  xh_min = heapq.heappop(XH)
  # left + D の位置で攻撃する
  left = xh_min[0]
  right = left + width
  nAttack = (xh_min[1] + A - 1) // A
  damage = nAttack * A
    
  target = []
  while len(XH) != 0:
    xh = heapq.heappop(XH)
    if xh[0] <= right:
      if xh[1] > damage:
        target.append(xh)
    else:
      heapq.heappush(XH, xh)
      break
  if len(XH) == 0:
    maxH = xh_min[1]
    if len(target):
      maxH = max(xh_min[1], max([t[1] for t in target]))
    nAttack = (maxH + A - 1) // A
    ans += nAttack
  else:
    ans += nAttack
    for t in target:
      heapq.heappush(XH, (t[0], t[1] - damage))
  
print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
import heapq

N, D, A = map(int, readline().split())
m = map(int,read().split())
XH = list(zip(m,m))
heapq.heapify(XH)
width = 2*D

ans = 0
while len(XH) != 0:
  xh_min = heapq.heappop(XH)
  # left + D の位置で攻撃する
  left = xh_min[0]
  right = left + width
  nAttack = (xh_min[1] + A - 1) // A
  ans += nAttack
  damage = nAttack * A
  target = []
  while len(XH) != 0:
    xh = heapq.heappop(XH)
    if xh[0] <= right:
      if xh[1] > damage:
        target.append(xh)
    else:
      heapq.heappush(XH, xh)
      break
  for t in target:
    heapq.heappush(XH, (t[0], t[1] - damage))
  
print(ans)


Fixed submission:
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
import heapq

N, D, A = map(int, readline().split())
m = map(int,read().split())
XH = list(zip(m,m))
heapq.heapify(XH)
width = 2*D

ans = 0
while len(XH) != 0:
  xh_min = heapq.heappop(XH)
  # left + D の位置で攻撃する
  left = xh_min[0]
  right = left + width
  nAttack = (xh_min[1] + A - 1) // A
  damage = nAttack * A
    
  target = []
  while len(XH) != 0:
    xh = heapq.heappop(XH)
    if xh[0] <= right:
      if xh[1] > damage:
        target.append(xh)
    else:
      heapq.heappush(XH, xh)
      break
  if len(XH) == 0:
    maxH = xh_min[1]
    if len(target):
      maxH = max(xh_min[1], max([t[1] for t in target]))
    nAttack = (maxH + A - 1) // A
    ans += nAttack
  else:
    ans += nAttack
    for t in target:
      heapq.heappush(XH, (t[0], t[1] - damage))
  
print(ans)