线段树区间修改入门题目。快被这个长整形给整死啦。以后如果对自己的算法的正确性有80%的把握,就去看一下细节,非常认真的看一遍,一行一行的看,这样其实更省时间,就比如我这次调来调去,调了4个多小时,最后才突然发现。
//线.3段树区间修改
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
const int maxn=100000;
__int64 sum[maxn*3],d[maxn*3];
int v[maxn+10];
int n,q;
int ql,qr,c;
__int64 _sum;
__int64 build(int node,int l,int r)
{
if(l==r) return sum[node]=v[l];
else
{
int mid=l+(r-l)/2;
sum[node]=build(node*2,l,mid)+build(node*2+1,mid+1,r);
}
}
void update(int node,int l,int r)
{
if(l>=ql&&r<=qr)
{
d[node]+=c;
sum[node]+=c*(r-l+1);
}
else
{
int m=l+(r-l)/2;
if(ql<=m) update(node*2,l,m);
if(qr>m) update(node*2+1,m+1,r);
sum[node]=sum[node*2]+sum[node*2+1]+d[node]*(r-l+1);//要十分注意这一步,此节点随着子节点的更新而更新,sum值不仅把子节点的sum值相加,
//因为子节点的相加,把本节点的直接修改给抹去了,所以还需加上本节点的修改的值
}
}
void query(int node,int l,int r,__int64 _add)
{
if(l>=ql&&r<=qr)
{
_sum+=sum[node]+(r-l+1)*_add;
}
else
{
__int64 tem=0;
int m=l+(r-l)/2;
if(ql<=m) query(node*2,l,m,_add+d[node]);
if(qr>m) query(node*2+1,m+1,r,_add+d[node]);
}
}
int main()
{
while(~scanf("%d%d",&n,&q))
{
memset(sum,0,sizeof(sum));
memset(d,0,sizeof(d));
int i;
for(i=1;i<=n;i++) scanf("%d",&v[i]);
build(1,1,maxn);
char t;
for(i=0;i<q;i++)
{
getchar();
scanf("%c",&t);
if(t=='Q')
{
scanf("%d%d",&ql,&qr);
_sum=0;
query(1,1,maxn,0);
printf("%I64d\n",_sum);
}
else
{
scanf("%d%d%d",&ql,&qr,&c);
update(1,1,maxn);
}
}
}
return 0;
}