相比較於單點更新和單點查詢來說
區間更新多了一個pushdown函數
代碼如下
void pushdown(int root,int m){
if(add[root]){
add[root<<1] += add[root];
add[root<<1 | 1] += add[root];
sum[root<<1] += add[root]*(m-(m>>1));
sum[root<<1 | 1] += add[root]*(m>>1);
add[root] = 0;
}
}
假如我們要更新(2,3)區間,區間每個值加val
(2,3)區間的子區間(2,2),(3,3)就也要更新
這時我們增加一個add標記
如果(2,3)區間的每個值要加val
向下的每個區間也要加val
就有
add[root<<1] += add[root];
add[root<<1 | 1] += add[root];
之後的sum就根據這個區間的長度去更新
代碼如下<pre name="code" class="cpp">/********************************************
Author :Crystal
Created Time :
File Name :
********************************************/
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <string>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <cctype>
using namespace std;
typedef long long ll;
typedef pair<int ,int> pii;
#define MEM(a,b) memset(a,b,sizeof a)
#define CLR(a) memset(a,0,sizeof a);
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
//#define LOCAL
int ans[500005];
ll add[500005];
ll sum[500006];
void pushup(int root){
sum[root] = sum[root*2] + sum[root*2+1];
}
void pushdown(int root,int m){
if(add[root]){
add[root<<1] += add[root];
add[root<<1 | 1] += add[root];
sum[root<<1] += add[root]*(m-(m>>1));
sum[root<<1 | 1] += add[root]*(m>>1);
add[root] = 0;
}
}
void build(int l,int r,int root){
add[root] = 0;
if(l == r){
scanf("%lld",&sum[root]);
return;
}
int m = (l+r)>>1;
build(l,m,root*2);
build(m+1,r,root*2+1);
pushup(root);
return;
}
void update(int l,int r,int root,int ls,int rs,int val){
if(l>=ls && r <= rs){
sum[root] += (ll)val*(r-l+1);
add[root] += val;
return;
}
pushdown(root,r-l+1);
int m = (l+r)>>1;
if(ls <= m)update(l,m,root<<1,ls,rs,val);
if(rs>m)update(m+1,r,root<<1|1,ls,rs,val);
pushup(root);
}
ll query(int l,int r,int root,int ls,int rs){
if(l>=ls && r <= rs){
return sum[root];
}
pushdown(root,r-l+1);
int m = (l+r)>>1;
ll res = 0;
if(ls <= m)res += query(l,m,root*2,ls,rs);
if(rs > m)res += query(m+1,r,root*2+1,ls,rs);
return res;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
int n,m;
while(cin >> n >> m){
//cout << n << endl;
build(1,n,1);
for(int i=1;i<=m;i++){
char q[10];
scanf("%s",q);
if(q[0]=='Q'){
int a,b;scanf("%d%d",&a,&b);
printf("%lld\n",query(1,n,1,a,b));
}
else{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
update(1,n,1,a,b,c);
}
}
}
return 0;
}