#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stdlib.h>
#include<iostream>
using namespace std;
#define ll long long
const int maxn=100005;
ll tree[maxn*4];
int a[maxn];
ll tag[maxn*4];
void build(int rt,int l,int r){
if(l==r){
tree[rt]=a[l];
return ;
}
int mid=l+r>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void pushdown(int rt,int l,int r){
int mid=l+r>>1;
tag[rt<<1]+=tag[rt];
tag[rt<<1|1]+=tag[rt];
tree[rt<<1]+=tag[rt]*(mid-l+1);
tree[rt<<1|1]+=tag[rt]*(r-mid);
tag[rt]=0;
}
void change(int rt,int l,int r,int x,int y,int c){
if(l==x&&r==y){
tree[rt]+=(r-l+1)*c;
tag[rt]+=c;
return ;
}
pushdown(rt,l,r);
int mid=l+r>>1;
if(y<=mid)
change(rt<<1,l,mid,x,y,c);
else if(x>mid)
change(rt<<1|1,mid+1,r,x,y,c);
else{
change(rt<<1,l,mid,x,mid,c);
change(rt<<1|1,mid+1,r,mid+1,y,c);
}
tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
ll query(int rt,int l,int r,int x,int y){
if(l==x&&r==y){
return tree[rt];
}
pushdown(rt,l,r);
int mid=l+r>>1;
if(y<=mid)
return query(rt<<1,l,mid,x,y);
else if(x>mid)
return query(rt<<1|1,mid+1,r,x,y);
else
return query(rt<<1,l,mid,x,mid)+query(rt<<1|1,mid+1,r,mid+1,y);
}
int main(){
int n,q;
scanf("%d%d",&n,&q);
memset(tag,0,sizeof(tag));
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
while(q--){
char str[10];
scanf("%s",str);
if(str[0]=='Q'){
int x,y;
scanf("%d%d",&x,&y);
printf("%lld\n",query(1,1,n,x,y));
}
else{
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
change(1,1,n,x,y,c);
}
}
return 0;
}
线段树lazytag标记
最新推荐文章于 2025-12-02 14:45:04 发布
本文介绍了一种使用线段树实现区间更新和查询的方法,包括构建线段树、区间加法更新及懒惰传播等核心操作。适用于解决大规模数组上的区间修改与查询问题。

793

被折叠的 条评论
为什么被折叠?



