敢不敢把刚刚复制粘贴的东西发出来?

发布时间:
2025-01-06 06:21
阅读量:
5

def bulid(p,pl,pr): #建树

if pl==pr:

tree[p]=a[pl]

return

mid=(pl+pr)>>1

bulid(p<<1,pl,mid)

bulid(p<<1|1,mid+1,pr)

tree[p]=tree[p<<1]+tree[p<<1|1] #push_up(p)


def addtag(p,pl,pr,d): #给结点p打tag标记,并更新tree

tag[p]+=d #打上tag标记

tree[p]+=d*(pr-pl+1) #计算新的tree


def push_down(p,pl,pr):

if tag[p]>0: #有tag标记,这是以前做区间修改时留下的

mid=(pl+pr)>>1

addtag(p<<1,pl,mid,tag[p]) #把tag标记传给左子树

addtag(p<<1|1,mid+1,pr,tag[p]) #将tag标记传给右子树

tag[p]=0 #p自己的tag被传走了


def update(L,R,p,pl,pr,d):

if L<=pl and pr<=R: #在这个区间里面

addtag(p,pl,pr,d)

return

push_down(p,pl,pr) #将懒惰标记传递给孩子.tree[p]不能完全被包含在需要修改的区间[L,R]中,需要解决多次修改的冲突问题

mid=(pl+pr)>>1

if L<=mid:

update(L,R,p<<1,pl,mid,d)

if R>=mid+1:

update(L,R,p<<1|1,mid+1,pr,d)

tree[p]=tree[p<<1]+tree[p<<1|1] #push_up(p)


def query(L,R,p,pl,pr):

if L<=pl and pr<=R:

return tree[p]

push_down(p,pl,pr)

res=0

mid=(pl+pr)>>1

if L<=mid:

res+=query(L,R,p<<1,pl,mid)

if R>mid:

res+=query(L,R,p<<1|1,mid+1,pr)

return res


n,m=map(int,input().split())

a=[0]+list(map(int,input().split()))

tag=[0]*(len(a)<<2) #4倍大

tree=[0]*(len(a)<<2)

bulid(1,1,n) #建树

for i in range(m):

w=list(map(int,input().split()))

if len(w)==3: #区间查询:[L,R]的区间和

q,L,R=w

print(query(L,R,1,1,n))

else: #区间修改:把[L,R]的每个元素加上d

q,L,R,d=w

update(L,R,1,1,n,d)

END