T - A Simple Problem with Integers (线段树&区间修改)
思路:线段树&lazy_tag板子题。
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+5;
typedef long long ll;
ll tr[N*10];
ll lz[N*10];
void re(int x){
tr[x]=tr[x<<1]+tr[x<<1|1];
}
void push_down(int x,int len){
if(lz[x]){
lz[x<<1]+=lz[x],lz[x<<1|1]+=lz[x];
tr[x<<1]+=(len-(len>>1))*lz[x];
tr[x<<1|1]+=(len>>1)*lz[x];
lz[x]=0;
}
}
void build(int st,int ed,int x){
if(st==ed){
scanf("%lld",&tr[x]);
return;
}
int mid=(st+ed)>>1;
build(st,mid,x<<1);
build(mid+1,ed,x<<1|1);
re(x);
}
void update(int st,int ed,int x,int l,int r,int val){
if(st>=l&&ed<=r){
tr[x]+=(ll)(ed-st+1)*val; //更新区间和,并标记lazy_tag
lz[x]+=val;
return;
}
push_down(x,ed-st+1);//如果原来有lazy_tag则下放lazy_tag
int mid=(st+ed)>>1;
if(l<=mid) update(st,mid,x<<1,l,r,val);
if(r>mid) update(mid+1,ed,x<<1|1,l,r,val);
re(x);
}
ll query(int st,int ed,int x,int l,int r){
if(r<st||l>ed) return 0;
else if(st>=l&&ed<=r) return tr[x];
push_down(x,ed-st+1);//当查询到该区间时如果原来有lazy_tag则下放lazy_tag
int mid=(st+ed)>>1;
return query(st,mid,x<<1,l,r)+query(mid+1,ed,x<<1|1,l,r);
}
int main(){
int n,q;
scanf("%d%d",&n,&q);
build(1,n,1);
/*for(int i=1;i<=20;i++) printf("tr[%d]=%d\n",i,tr[i]); puts(""); */
while(q--){
char op;
int a,b,c;
scanf("\n%c",&op);
if(op=='Q'){
scanf("%d%d",&a,&b);
printf("%lld\n",query(1,n,1,a,b));
}
else scanf("%d%d%d",&a,&b,&c),update(1,n,1,a,b,c);
}
return 0;
}