您的位置:首页 > 其它

poj3468(线段树成段更新)

2013-02-24 10:37 197 查看
题目大意:输入第一行,两个整数n,m,第二行给出n个数的一个序列,接下来m行,每行给出一个操作。操作有两种形式,1."C a b c" 表示将 Aa, Aa+1, ... , Ab.加上c.

2."Q a b" 输出区间[a,b]的和。

#include<stdio.h>
#define maxn 100010
struct node
{
int l,r;//线段树区间
int mid;//线段树区间中间值
_int64 sum,mark;//poj不支持_int64,要用long long
}p[maxn<<2];//注意这里不能写成p[maxn*2];否则RE
int a[maxn];
void build(int id,int l,int r)
{
p[id].l=l;
p[id].r=r;
p[id].mid=(l+r)>>1;
p[id].mark=0;
if(l==r){
p[id].sum=a[l];
return;
}
int m=(l+r)>>1;
build(2*id,l,m);
build(2*id+1,m+1,r);
p[id].sum=p[id*2].sum+p[id*2+1].sum;
}
void update(int id,int l,int r,int val)
{
if(p[id].l==l&&p[id].r==r){
p[id].mark+=val;
return;
}
p[id].sum+=val*(r-l+1);
if(p[id].mid>=r) update(2*id,l,r,val);
else if(p[id].mid<l) update(id*2+1,l,r,val);
else{
update(id*2,l,p[id].mid,val);
update(id*2+1,p[id].mid+1,r,val);
}
}
_int64 query(int id,int l,int r)
{
if(p[id].l==l&&p[id].r==r) return p[id].sum+p[id].mark*(r-l+1);
if(p[id].mark){
p[id*2].mark+=p[id].mark;
p[id*2+1].mark+=p[id].mark;
p[id].sum+=(p[id].r-p[id].l+1)*p[id].mark;
p[id].mark=0;
}
if(p[id].mid>=r) return query(id*2,l,r);
else if(p[id].mid<l) return query(id*2+1,l,r);
else return query(id*2,l,p[id].mid)+query(id*2+1,p[id].mid+1,r);
}
int main()
{
freopen("poj3468.input.txt","r",stdin);
int n,m,b,c,d,i;
char str[5];
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
for(i=0;i<m;i++)
{
scanf("%s",str);
if(str[0]=='Q'){
scanf("%d%d",&b,&c);
printf("%I64d\n",query(1,b,c));//poj上用lld
}
else if(str[0]=='C'){
scanf("%d%d%d",&b,&c,&d);
update(1,b,c,d);
}
}
return 0;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Poj