POJ 3468<线段树,区间add>
//位运算
k<<1 相当于 k*2
k<<1|1 相当于 k*2+1
/*
修改区间内的值,并且维护区间和。
详见代码
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=100000+10;
int a[maxn];
struct tree
{
int l,r;
LL sum;
LL Inc;//延迟标记变量,表示[l,r]区间每个数增加Inc.
}f[maxn*4];
void bulid(int i,int l,int r)//maketree
{
f[i].l=l;
f[i].r=r;
f[i].Inc=0;
if(l==r)
{
f[i].sum=a[l];//是a[l]不能是a[i],i代表的是节点的编号,在最后一行,l或者r代表的是第i个节点的次序。
return ;
}
int mid=(l+r)>>1;
bulid(i<<1, l, mid);
bulid(i<<1|1, mid+1, r);
f[i].sum=f[i<<1].sum+f[i<<1|1].sum;//维护和
}
void add(int i,int a,int b,LL c)
{
if(f[i].l==a&&f[i].r==b)//区间重合,直接标记Inc+=c;
{
f[i].Inc+=c;
return ;
}
//区间不重合,更新当前区间的sum,pushdown
f[i].sum+=c*(b-a+1);
int mid=(f[i].l+f[i].r)>>1;
if(b<=mid)
add(i<<1, a, b, c);
else if(a>=mid+1)
add(i<<1|1, a, b, c);
else
{
add(i<<1, a,mid, c);
add(i<<1|1,mid+1,b,c);
}
}
LL query(int i,int a,int b)//查询
{
if(f[i].l==a&&f[i].r==b)//区间重合
{
return f[i].sum+f[i].Inc*(b-a+1);
}
f[i].sum+=(f[i].r-f[i].l+1)*f[i].Inc;//相当于pushdown
int mid=(f[i].l+f[i].r)>>1;
add(i<<1, f[i].l, mid, f[i].Inc);
add(i<<1|1,mid+1,f[i].r,f[i].Inc);
f[i].Inc=0;
if(b<=mid)
return query(i<<1, a, b);
else if(a>=mid+1) return query(i<<1|1, a, b);
else return query(i<<1, a, mid)+query(i<<1|1, mid+1,b);
}
int main ()
{
int n,m;
char s[5];
int l,r;
LL c;
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
bulid(1, 1, n);
for(int i=1;i<=m;i++)
{
scanf("%s",s);
if(s[0]=='Q')
{
scanf("%d%d",&l,&r);
printf("%lld\n",query(1, l, r));
}
else
{
scanf("%d%d%lld",&l,&r,&c);
add(1, l, r, c);
}
}
}
return 0;
}
想的太多,做的太少。