POJ 3468
题意就不说了,之间看代码;
代码是对的,如果大佬觉得注释有问题可以说,会仔细更改?
#include<stdio.h>
#include<string.h>
#include<string>
#include<iostream>
#include<algorithm>
#include<queue>
#include<math.h>
#include<map>
#include<vector>
#include<stack>
#define inf 500005
using namespace std;
typedef long long ll;
const int N=800055;
ll tree[N],add[N];
ll m,n;
void build(ll a,ll b,ll r)//建树
{
if(a==b)
{
scanf("%lld",&tree[r]);
return;
}
ll mid=(a+b)/2;
build(a,mid,r<<1);//不断往下推,直到推到底端叶子(叶子就是树的最底端)
build(mid+1,b,r<<1|1);
tree[r]=tree[r<<1]+tree[r<<1|1];//节点是下面两个节点之和
}
void pushdown(ll r,ll lz,ll rz)//区间维护
{ //lz是在r节点左边的底端叶子数,rz代表是右边的底端叶子数
if(add[r])
{
add[r<<1]+=add[r];
add[r<<1|1]+=add[r];
tree[r<<1]+=add[r]*lz;
tree[r<<1|1]+=add[r]*rz;
add[r]=0;
}
}
void update(ll a,ll b,ll r,ll qa,ll qb,ll c)//区间更新
{
if(a>=qa&&b<=qb)
{
add[r]+=c;
tree[r]+=(b-a+1)*c;
return;
}
ll mid=(a+b)/2;
pushdown(r,mid+1-a,b-mid);
if(mid>=qa)//因为需要更改qa到qb这个区间,所以如果mid还大于qa就一直往左查
update(a,mid,r<<1,qa,qb,c);
if(mid<qb)//mid<qb就一直往右查
update(mid+1,b,r<<1|1,qa,qb,c);
tree[r]=tree[r<<1]+tree[r<<1|1];
}
ll qurey(ll a,ll b,ll r,ll qa,ll qb)//区间查询
{
if(a>=qa&&b<=qb)
return tree[r];
ll mid=(a+b)/2;
pushdown(r,mid+1-a,b-mid);//每次都需要向下维护区间
ll ans=0;
if(mid>=qa)//和上面的查询一样
ans+=qurey(a,mid,r<<1,qa,qb);
if(mid<qb)
ans+=qurey(mid+1,b,r<<1|1,qa,qb);
return ans;
}
int main()
{
while(~scanf("%lld %lld",&n,&m))
{
ll i,a,b,c;
char s;
build(1,n,1);
for(i=0;i<m;i++)
{
getchar();
scanf("%c",&s);
if(s=='C')
{
scanf("%lld %lld %lld",&a,&b,&c);
update(1,n,1,a,b,c);
}
else
{
scanf("%lld %lld",&a,&b);
ll ans=qurey(1,n,1,a,b);
printf("%lld\n",ans);
}
}
}
return 0;
}