计蒜客:区间整数操作-区间更新-区间和
给出N个整数A1,A2,..,Av,你需要处理区间加,区间求和。
输入格式
第一行两个整数N和Q(1≤N,Q≤105)。
第二行N个整数,表示A1,A2...Av(|A;≤109)的初始值。
接下来Q行,每行一个操作:
cabc,表示Aa,Aa+1…Ab每个数加c(lcl≤10000)。
Qab,表示询问Aa,Aa+1..Ab的和,答案可能超过32位整数。
输出格式
对于所有Q询问,一行输出一个答案。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
/*区间更新,区间加值--区间求和*/
const int MAX_N = 1e5+5;
ll s[4 * MAX_N],col[4 * MAX_N];
int n,q;
//父节点合并
void up(int p){
s[p] = s[p * 2] + s[p * 2 + 1];
}
//向下更新一层 区间更新使用延迟更新的思想提高效率
void down(int p, int l, int r){
if(col[p]){
int mid = (l + r) / 2;
s[p * 2] += col[p] * (mid - l + 1);
s[p * 2 + 1] += col[p] * (r - mid);
col[p * 2] += col[p];
col[p * 2 + 1] += col[p];
col[p] = 0;
}
}
//更新
void modify(int p,int l,int r,int x,int y,int c){
if(x <= l && r <=y){
s[p] += (r - l + 1) * c; //对父结点修改 如何是求区间最值而不是求和该如何修改呢?
col[p] += c; //标记子节点需要延迟更新
return;
}
down(p, l, r);//向下更新一层
int mid = (l + r)/2;
if(x <= mid){
modify(p * 2, l, mid, x, y, c);
}
if(y > mid){
modify(p * 2 + 1, mid + 1,r,x,y,c);
}
up(p);
}
//查询
ll query(int p,int l,int r,int x,int y){
if(x <= l && r <= y){
return s[p];
}
down(p,l,r);//如果没有return,这时子节点必须更新了 就向下更新一层
int mid = (l + r) / 2;
ll res = 0;
if(x <= mid){
res += query(p * 2, l,mid,x,y);
}
if(y > mid){
res += query(p * 2 + 1,mid + 1,r,x,y);
}
return res;
}
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
ll d;
scanf("%ld",&d);
modify(1,1,n,i,i,d);
}
char ins;
while(q--){
scanf(" %c",&ins);
int a,b;
ll c;
if(ins=='Q'){
scanf("%d%d",&a,&b);
printf("%lld\n",query(1,1,n,a,b));
}else{
scanf("%d%d%ld",&a,&b,&c);
modify(1,1,n,a,b,c);
}
}
return 0;
}