A Simple Problem with Integers
题目连接:http://poj.org/problem?id=3468
题目大意:给出一个数组,要求对一个区间所有的值加某一个数或者计算某一区间所有值的和。
题目思路:利用线段树处理,具体见代码
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 100010
struct Node{
int L;
int R;
long long add;///表示左右结点的区间都要增加add
long long sum;///该节点在更新之前的值
}tree[4*N];
///建树
void BuildTree(int root,int l,int r){
tree[root].L=l;
tree[root].R=r;
tree[root].add=0;
tree[root].sum=0;
if(l==r){
int a;
scanf("%d",&a);
tree[root].sum=a;///根节点的sum就为本身
return ;
}
int mid=(l+r)/2;
BuildTree(2*root,l,mid);
BuildTree(2*root+1,mid+1,r);
tree[root].sum=tree[2*root].sum+tree[2*root+1].sum;///父节点的sum等于两子节点的和
}
///区间更新
void Update(int root,int s,int e,long long v){
if(tree[root].L==s&&tree[root].R==e){
tree[root].add+=v;///因为区间的数每个都要加v,所有直接令add+v。。此时子节点还未更新
return ;
}
tree[root].sum+=v*(e-s+1);///区间不匹配,不能每个都加,则将要加的数总和直接赋给sum
int mid=(tree[root].L+tree[root].R)/2;
if(e<=mid) Update(2*root,s,e,v);
else if(s>mid) Update(2*root+1,s,e,v);
else {
Update(2*root,s,mid,v);
Update(2*root+1,mid+1,e,v);
}
}
///区间求和
long long QuerySum(int root,int s,int e){
if(tree[root].L==s&&tree[root].R==e){
return tree[root].sum+(e-s+1)*tree[root].add;///区间匹配,结果为结点本身的sum加上区间还有每个数都要加的add
}
int mid=(tree[root].L+tree[root].R)/2;
///更新子节点
tree[root].sum+=(tree[root].R-tree[root].L+1)*tree[root].add;
Update(2*root,tree[root].L,mid,tree[root].add);
Update(2*root+1,mid+1,tree[root].R,tree[root].add);
tree[root].add=0;
if(e<=mid) return QuerySum(2*root,s,e);
else if(s>mid) return QuerySum(2*root+1,s,e);
else {
return QuerySum(2*root,s,mid)+QuerySum(2*root+1,mid+1,e);
}
}
int main(){
int n,q;
scanf("%d%d",&n,&q);
BuildTree(1,1,n);
while(q--){
char s[4];
scanf("%s",s);
if(s[0]=='Q'){
int a,b;
scanf("%d%d",&a,&b);
printf("%I64d\n",QuerySum(1,a,b));
}
else{
int a,b;
long long c;
scanf("%d%d%I64d",&a,&b,&c);
Update(1,a,b,c);
}
}
return 0;
}