社区讨论

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 条回复,欢迎继续交流。

正在加载回复...