思路:线段树的初步进阶使用,主要思想是每一个节点中增加一个inc储存增加的量, 具体使用方法详见代码(参考自kuangbin大牛)
#include <iostream>
#include <stdio.h>
#include <cstring>
#define MAXN 1000000
using namespace std;
typedef long long ll;
struct note
{
long long ll,rr;
long long nsum,inc;
}q[MAXN*3];
long long aa[MAXN];
void build(long long i,long long l,long long r)
{
q[i].rr=r;
q[i].ll=l;
q[i].inc=0;
if(l==r)
{
q[i].nsum=aa[l];
return ;
}
long long m=(l+r)/2;
build(i*2,l,m);
build(i*2+1,m+1,r);
q[i].nsum=q[i*2].nsum+q[i*2+1].nsum;
}
void add(long long i,long long l,long long r,long long c)
{
if(q[i].ll==l&&q[i].rr==r)
{
q[i].inc+=c;
return ;
}
q[i].nsum+=c*(r-l+1);
long long m=(q[i].ll+q[i].rr)/2;
if(r<=m)
add(i*2,l,r,c);
else if(l>m)
add(i*2+1,l,r,c);
else
{
add(i*2,l,m,c);
add(i*2+1,m+1,r,c);;
}
}
long long query (long long i ,long long l,long long r)
{
if(q[i].ll==l&&q[i].rr==r)
{
return q[i].nsum+q[i].inc*(r-l+1);
}
q[i].nsum+=q[i].inc*(q[i].rr-q[i].ll+1);
long long m=(q[i].ll+q[i].rr)/2;
add(i*2,q[i].ll,m,q[i].inc);
add(i*2+1,m+1,q[i].rr,q[i].inc);
q[i].inc=0;
if(r<=m)
return query(i*2,l,r);
else if(l>m)
return query(i*2+1,l,r);
else
return query(i*2,l,m)+query(i*2+1,m+1,r);
}
int main()
{
// freopen("in.txt","r",stdin);
long long n,m;
while(scanf("%lld%lld",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%lld",&aa[i]);
}
build(1,1,n);
char t[3];
for(int i=0;i<m;i++)
{
long long a,b,c;
scanf("%s",t);
if(t[0]=='Q')
{
scanf("%lld%lld",&a,&b);
printf("%lld\n",query(1,a,b));
}
else
{
scanf("%lld%lld%lld",&a,&b,&c);
add(1,a,b,c);
}
}
}
}