题意:n个数,你可以给一个区间加上c,或者询问一个区间的和。
思路:线段树(成段更新)。简直模版得不能再模板。。不过我还是因为不熟练写了好些bug。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctype.h>
#define ll long long
using namespace std;
struct node{
int l,r;
ll val;
ll add;
};
node tree[400010];
ll num[100010];
ll build_tree(int n,int l,int r){
tree[n].l=l; tree[n].r=r; tree[n].add=0;
if(l==r){
tree[n].val=num[l];
return num[l];
}
int mid=(l+r)/2;
tree[n].val=build_tree(n*2,l,mid)+build_tree(n*2+1,mid+1,r);
return tree[n].val;
}
void update(int n,int l,int r,ll v){
tree[n].val+=(r-l+1)*v;
if(tree[n].l==l&&tree[n].r==r){
if(l!=r)tree[n].add+=v;
return;
}
int mid=(tree[n].l+tree[n].r)/2;
if(tree[n].add){
update(n*2,tree[n].l,mid,tree[n].add);
update(n*2+1,mid+1,tree[n].r,tree[n].add);
tree[n].add=0;
}
if(r<=mid){
update(n*2,l,r,v);
}else{
if(l<=mid){
update(n*2,l,mid,v);
update(n*2+1,mid+1,r,v);
}else{
update(n*2+1,l,r,v);
}
}
}
ll query(int n,int l,int r){
if(tree[n].l==l&&tree[n].r==r){
return tree[n].val;
}
int mid=(tree[n].l+tree[n].r)/2;
if(tree[n].add){
update(n*2,tree[n].l,mid,tree[n].add);
update(n*2+1,mid+1,tree[n].r,tree[n].add);
tree[n].add=0;
}
//
if(r<=mid){
return query(n*2,l,r);
}else{
if(l<=mid){
return query(n*2,l,mid)+query(n*2+1,mid+1,r);
}else{
return query(n*2+1,l,r);
}
}
}
int main(){
int n,q;
while(cin>>n>>q){
for(int i=1;i<=n;i++){
scanf("%lld",&num[i]);
}
build_tree(1,1,n);
while(q--){
char str[10];
scanf("%s",str);
if(str[0]=='C'){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
update(1,a,b,c);
}else{
int a,b;
scanf("%d%d",&a,&b);
ll ans=query(1,a,b);
printf("%lld\n",ans);
}
}
}
return 0;
}