http://poj.org/problem?id=3468
题目大意:
给你n个整数,两种操作,
求一段区间的和
一段区间内全部加上某个整数
简单线段树题
区间内一部分是固定区间和
另一个是此区间内每个数都需要加的量
注意用64为整数
详情见代码注释:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
const int N=100005;
struct node
{
int l,r;
long long add;//非固定,需要向下传递的量
long long v;//固定住的和
}mem[N*4];
int a[N];
long long ans;
void build(int x,int l,int r)
{
mem[x].l=l;
mem[x].r=r;
mem[x].add=0;//初始化
if(l==r)
{
mem[x].v=a[l];
}
else
{
int mid=(l+r)>>1;
build(x*2,l,mid);
build(x*2+1,mid+1,r);
mem[x].v=mem[x*2].v+mem[x*2+1].v;
}
}
void findsum(int x,int i,int j)
{
if(mem[x].l==i&&mem[x].r==j)
{
ans=ans+mem[x].v+(mem[x].r-mem[x].l+1)*mem[x].add;//如果正好是这个区间
}
else
{
int mid=(mem[x].l+mem[x].r)>>1;
mem[x].v+=(mem[x].r-mem[x].l+1)*mem[x].add;//否则向下传递,首先本区间固定量增加
mem[x*2].add+=mem[x].add;mem[x*2+1].add+=mem[x].add;//然后传给左右区间
mem[x].add=0;//最后清零
if(j<=mid)
{
findsum(x*2,i,j);
}else if(i>mid)
{
findsum(x*2+1,i,j);
}else
{
findsum(x*2,i,mid);
findsum(x*2+1,mid+1,j);
}
}
}
void Addint(int x,int i,int j,int k)
{
if(mem[x].l==i&&mem[x].r==j)
{
mem[x].add+=k;//本区间改变增加量
}
else
{
mem[x].v+=(j-i+1)*k;//向下的话,首先本区间先将固定量增加
int mid=(mem[x].l+mem[x].r)>>1;
if(j<=mid)
{
Addint(x*2,i,j,k);
}else if(i>mid)
{
Addint(x*2+1,i,j,k);
}else
{
Addint(x*2,i,mid,k);
Addint(x*2+1,mid+1,j,k);
}
}
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
}
build(1,1,n);
while(m--)
{
char c;
int i,j,k;
getchar();//吃换行
scanf("%c",&c);
if(c=='Q')
{
scanf("%d %d",&i,&j);
ans=0;
findsum(1,i,j);
printf("%I64d\n",ans);
}
else
{
scanf("%d %d %d",&i,&j,&k);
Addint(1,i,j,k);
}
}
}
return 0;
}