社区讨论
WA求条
P3372【模板】线段树 1参与者 2已保存回复 3
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @mhjsbzbv
- 此快照首次捕获于
- 2025/11/04 07:42 4 个月前
- 此快照最后确认于
- 2025/11/04 07:42 4 个月前
CPP
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,a[100010],tree[400010],tag[400010];
int ls(ll p){return p<<1;} //p*2
int rs(ll p){return p<<1|1;} //p*2+1
void push_up(ll p){
tree[p]=tree[ls(p)]+tree[rs(p)];
}
void build(ll p,ll pl,ll pr){ //节点p指向区间[pl,pr]
if(pl==pr){tree[p]=a[pl];return;}
ll mid=pl+pr>>1; //(pl+pr)/2
build(ls(p),pl,mid);//节点p的左儿子指向区间[pl,mid]
build(rs(p),mid+1,pr);//节点p的右儿子指向区间[mid+1,pr]
push_up(p);
}
void addtag(ll p,ll pl,ll pr,ll d){
tag[p]+=d;
tree[p]+=d*(pr-pl+1);//区间内元素分别加d,故区间节点加d*元素数
}
void push_down(ll p,ll pl,ll pr){ //不能覆盖时,把tag传递给子树
if(tag[p]){
ll mid=(pl+pr)>>1;
addtag(ls(p),pl,mid,tag[p]);
addtag(rs(p),mid+1,pr,tag[p]);
tag[p]=0;
}
}
void update(ll L,ll R,ll p,ll pl,ll pr,ll d){ //区间修改
if(L<=pl&&pr<=R){
addtag(p,pl,pr,d);
return;
}
push_down(p,pl,pr);
ll mid=(pl+pr)>>1;
if(L<=mid) update(L,R,ls(p),pl,mid,d);
if(R>mid) update(L,R,rs(p),mid+1,pr,d);
push_up(p);
}
ll query(ll L,ll R,ll p,ll pl,ll pr){ //查询区间左端点L,查询区间右端点R,调用query(L,R,查找节点,ls(查找节点),rs(查找节点))
if(L<=pl&&pr<=R) return tree[p];//完全覆盖
ll mid=(pl+pr)>>1,res=0;
if(L<=mid) res+=query(L,R,ls(p),pl,mid); //L与左子结点有重叠
if(R>mid) res+=query(L,R,rs(p),mid+1,pr);//R与右子结点有重叠
return res;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
for(int i=1;i<=n;i++){
ll v,L,R,d;
cin>>v;
if(v==1){
cin>>L>>R>>d;
update(L,R,1,1,n,d);
}
else{
cin>>L>>R;
cout<<query(L,R,1,1,n)<<endl;
}
}
return 0;
}
扪心不会线段树求dalao看看,不要AC代码谢谢
回复
共 3 条回复,欢迎继续交流。
正在加载回复...