Buggy python submission (verdict: Time Limit Exceeded):
class StarrySkyTree:
    """ Starry Sky Tree(区間加算・区間最小(大)値取得) """

    def __init__(self, N, func, intv):
        """
        N:要素数
        func:計算式(maxなど)
        intv:単位元
        """
        self.intv = intv
        self.func = func
        LV = (N-1).bit_length()
        self.N0 = 2**LV
        self.data = [0]*(2*self.N0)
        self.lazy = [0]*(2*self.N0)

    # 伝搬される区間のインデックス(1-indexed)を全て列挙するgenerator
    def gindex(self, l, r):
        L = l + self.N0; R = r + self.N0
        lm = (L // (L & -L)) >> 1
        rm = (R // (R & -R)) >> 1
        while L < R:
            if R <= rm:
                yield R
            if L <= lm:
                yield L
            L >>= 1; R >>= 1
        while L:
            yield L
            L >>= 1

    # 遅延評価の伝搬処理
    def propagates(self, *ids):
        # 1-indexedで単調増加のインデックスリスト
        for i in reversed(ids):
            v = self.lazy[i-1]
            if not v:
                continue
            self.lazy[2*i-1] += v; self.lazy[2*i] += v
            self.data[2*i-1] += v; self.data[2*i] += v
            self.lazy[i-1] = 0

    def update(self, l, r, x):
        """ 区間[l,r)の値にxを加算 """

        # 1. lazyの値は伝搬させない
        # 2. 区間[l,r)のdata, lazyの値を更新
        L = self.N0 + l; R = self.N0 + r
        while L < R:
            if R & 1:
                R -= 1
                self.lazy[R-1] += x; self.data[R-1] += x
            if L & 1:
                self.lazy[L-1] += x; self.data[L-1] += x
                L += 1
            L >>= 1; R >>= 1
        # 3. 更新される区間を部分的に含んだ区間のdataの値を更新 (lazyの値を考慮)
        for i in self.gindex(l, r):
            self.data[i-1] = self.func(self.data[2*i-1], self.data[2*i]) + self.lazy[i-1]

    def query(self, l, r):
        """ 区間[l,r)の最小(大)値を取得 """

        # 1. トップダウンにlazyの値を伝搬
        self.propagates(*self.gindex(l, r))
        L = self.N0 + l; R = self.N0 + r

        # 2. 区間[l, r)の最小(大)値を求める
        s = self.intv
        while L < R:
            if R & 1:
                R -= 1
                s = self.func(s, self.data[R-1])
            if L & 1:
                s = self.func(s, self.data[L-1])
                L += 1
            L >>= 1; R >>= 1
        return s

#####

import bisect




N,D,A=map(int,input().split())
XH=[[0,0] for _ in range(N)]

for i in range(N):
    XH[i][0],XH[i][1]=map(int,input().split())
    
XH.sort()

X=[0]*N
for i in range(N):
    X[i]=XH[i][0]


sst=StarrySkyTree(N+1, max, 0)

for i in range(N):
    sst.update(i,i+1,XH[i][1])
    
cnt=0
for i in range(N):
    h=sst.query(i,i+1)
    if h>0:
        r=bisect.bisect_right(X,X[i]+2*D)
        bomb=(h+A-1)//A#切り上げ
        sst.update(i,r,-1*bomb*A)
        cnt+=bomb
        
print(cnt)
        



Fixed submission:
import math
import bisect
import sys
input = sys.stdin.readline

N,D,A=map(int,input().split())  

XH=[[0,0] for _ in range(N)]
for i in range(N):
    x,h=map(int,input().split())
    XH[i][0]=x
    XH[i][1]=h
    
XH.sort()

X=[0]*N
for i in range(N):
    X[i]=XH[i][0]



ans=0
S=[0]*(N+1)#累積和


for i in range(N):
    if S[i]<XH[i][1]:
        bom=X[i]+D
        Lb=i
        Rb=bisect.bisect_right(X,bom+D)
        num=(XH[i][1]-S[i])//A
        if (XH[i][1]-S[i])%A!=0:
            num+=1
        ans+=num
        dam=num*A
        #imosで遅延
        S[Lb]+=dam
        S[Rb]-=dam
    S[i+1]+=S[i]
        
print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
import math
import bisect
import sys
input = sys.stdin.readline

N,D,A=map(int,input().split())  

XH=[[0,0] for _ in range(N)]
for i in range(N):
    x,h=map(int,input().split())
    XH[i][0]=x
    XH[i][1]=h
    
XH.sort()

X=[0]*N
for i in range(N):
    X[i]=XH[i][0]


#bの倍数の中でaを超える最小
def calc(a,b):
    return math.ceil(a/b)*b

ans=0
for i in range(N):
    if XH[i][1]>0:
        bom=X[i]+D
        Lb=i
        Rb=bisect.bisect_right(X,bom+D)
        ans+=XH[i][1]//A
        if XH[i][1]%A!=0:
            ans+=1
        dam=calc(XH[i][1],A)
        for j in range(Lb,Rb):
            XH[j][1]-=dam
        
print(ans)
    
    
    
    





Fixed submission:
import math
import bisect
import sys
input = sys.stdin.readline

N,D,A=map(int,input().split())  

XH=[[0,0] for _ in range(N)]
for i in range(N):
    x,h=map(int,input().split())
    XH[i][0]=x
    XH[i][1]=h
    
XH.sort()

X=[0]*N
for i in range(N):
    X[i]=XH[i][0]



ans=0
S=[0]*(N+1)#累積和


for i in range(N):
    if S[i]<XH[i][1]:
        bom=X[i]+D
        Lb=i
        Rb=bisect.bisect_right(X,bom+D)
        num=(XH[i][1]-S[i])//A
        if (XH[i][1]-S[i])%A!=0:
            num+=1
        ans+=num
        dam=num*A
        #imosで遅延
        S[Lb]+=dam
        S[Rb]-=dam
    S[i+1]+=S[i]
        
print(ans)

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

N,D,A=map(int,input().split())  

XH=[[0,0] for _ in range(N)]
for i in range(N):
    x,h=map(int,input().split())
    XH[i][0]=x
    XH[i][1]=h
    
XH.sort()

X=[0]*N
H=[0]*N
for i in range(N):
    X[i]=XH[i][0]
    H[i]=XH[i][1]


#bの倍数の中でaを超える最小
def calc(a,b):
    return math.ceil(a/b)*b

ans=0
for i in range(N):
    if H[i]>0:
        bom=X[i]+D
        Lb=i
        Rb=bisect.bisect_right(X,bom+D)
        ans+=H[i]//A
        if H[i]%A!=0:
            ans+=1
        dam=calc(H[i],A)
        for j in range(Lb,Rb):
            H[j]-=dam
        
print(ans)
    
    
    
    




Fixed submission:
import math
import bisect
import sys
input = sys.stdin.readline

N,D,A=map(int,input().split())  

XH=[[0,0] for _ in range(N)]
for i in range(N):
    x,h=map(int,input().split())
    XH[i][0]=x
    XH[i][1]=h
    
XH.sort()

X=[0]*N
for i in range(N):
    X[i]=XH[i][0]



ans=0
S=[0]*(N+1)#累積和


for i in range(N):
    if S[i]<XH[i][1]:
        bom=X[i]+D
        Lb=i
        Rb=bisect.bisect_right(X,bom+D)
        num=(XH[i][1]-S[i])//A
        if (XH[i][1]-S[i])%A!=0:
            num+=1
        ans+=num
        dam=num*A
        #imosで遅延
        S[Lb]+=dam
        S[Rb]-=dam
    S[i+1]+=S[i]
        
print(ans)