题意:
给你n个数,q个操作,操作有两种,‘Q a b ’是询问a~b这段数的和,‘C a b c’是把a~b这段数都加上c
可以用线段树,树状数组,伸展树
线段树:
/*线段树*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
const int N=100005;
int root;
struct tree{
ll val,lazy;
}node[N*4];
void pushDown(int rt,int l,int r){
if(node[rt].lazy!=0){
int mid=(l+r)>>1;
node[rt<<1].val+=node[rt].lazy*(mid-l+1);
node[rt<<1].lazy+=node[rt].lazy;
node[rt<<1|1].val+=node[rt].lazy*(r-mid);
node[rt<<1|1].lazy+=node[rt].lazy;
node[rt].lazy=0;
}
}
void pushUp(int rt,int l,int r){
node[rt].val=node[rt<<1].val+node[rt<<1|1].val;
}
void buildTree(int rt,int l,int r){
node[rt].lazy=0;
if(l==r){
scanf("%I64d",&node[rt].val);
return ;
}
int mid=(l+r)>>1;
buildTree(rt<<1,l,mid);
buildTree(rt<<1|1,mid+1,r);
pushUp(rt,l,r);
}
void update(int rt,int l,int r,int L,int R,int v){
if(L<=l&&R>=r){
node[rt].lazy+=v;
node[rt].val+=v*(r-l+1);
return ;
}
pushDown(rt,l,r);
int mid=(l+r)>>1;
if(L<=mid){
update(rt<<1,l,mid,L,R,v);
}
if(R>mid){
update(rt<<1|1,mid+1,r,L,R,v);
}
pushUp(rt,l,r);
}
ll query(int rt,int l,int r,int L,int R){
if(L<=l&&R>=r){
return node[rt].val;
}
pushDown(rt,l,r);
int mid=(l+r)>>1;
ll ans=0;
if(L<=mid)ans+=query(rt<<1,l,mid,L,R);
if(R>mid)ans+=query(rt<<1|1,mid+1,r,L,R);
return ans;
}
int main()
{
int m,n;
scanf("%d%d",&n,&m);
buildTree(1,1,n);
while(m--)
{
getchar();
char s;
int a,b,c;
s=getchar();
if(s=='Q')
{
scanf("%d%d",&a,&b);
printf("%I64d\n",query(1,1,n,a,b));
}
else
{
scanf("%d%d%d",&a,&b,&c);
update(1,1,n,a,b,c);
}
}
return 0;
}