您的位置:首页 > 其它

线段树系列-pku-3468-A Simple Problem with Integers-区间修改区间求和

2015-12-30 20:21 507 查看
一道简单的区间修改区间求和

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
struct seg {
int l,r,fa;
long long sum,more;
}tree[401111];
void build(int l,int r,int k) {
tree[k].l=l;
tree[k].r=r;
tree[k].fa=0;           //FA==1表示有该线段的加值
tree[k].more=0;         //more表示该线段的附加值
if(l==r) {
tree[k].sum=a[l];
tree[k].fa=1;
return;
}
int mid = (l+r) >> 1;
build(l,mid,2*k);
build(mid+1,r,2*k+1);
tree[k].sum=tree[2*k].sum+tree[2*k+1].sum;  //除附加值以外的和
}
void update(int l,int r,long long  v,int k) {
if(tree[k].l==l&&tree[k].r==r) {        //如果就是所加线段,直接赋值上附加值
tree[k].more+=v;
tree[k].fa=1;                       //并且标记
return;
}
int mid =(tree[k].l+tree[k].r) >> 1;
if (r<=mid) update(l,r,v,2*k);
else if(l>mid) update(l,r,v,2*k+1);
else {
update(l,mid,v,2*k);
update(mid+1,r,v,2*k+1);
}
tree[k].sum+=v*(r-l+1);             //因为不是对附加值进行操作,所以对sum进行加值
}
long long query(int l,int r,int k) {
long long ans=0;
if(tree[k].fa==1) {                 //统计是否有对应线段的附加值*点数
ans+=tree[k].more*(r-l+1);
}
if(tree[k].l==l&&tree[k].r==r) {
ans+= tree[k].sum;
return ans;
}
int mid=(tree[k].l+tree[k].r)>>1;
if(r<=mid) return ans+query(l,r,2*k);       //
else if(l>mid) return ans+query(l,r,2*k+1);
else {
return ans+query(l,mid,2*k)+query(mid+1,r,2*k+1);
}
}
int main()
{
int n,q;
char s[10];
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,n,1);
while(q--) {
scanf("%s",s);
if(s[0]=='Q') {
long long tot;
int x,y;
scanf("%d%d",&x,&y);
tot=query(x,y,1);
printf("%lld\n",tot);
}
else {
int x,y;
long long v;
scanf("%d%d%lld",&x,&y,&v);
update(x,y,v,1);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: