http://poj.org/problem?id=3468;
直接看代码吧:
#include<cstring>
#include<cstdio>
#include<algorithm>
#define maxn 100009
#define lson l,m,rt << 1
#define rson m+1,r,rt <<1|1
#define LL long long
using namespace std;
LL root[ maxn<<2 ];
LL sum[ maxn<<2 ];
LL tree[ maxn ];
void pushup(int rt)
{
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void pushdown(int rt,int k)
{
if( root[rt] )
{
int h = k>>1;
root[rt<<1] += root[rt];
root[rt<<1|1] += root[rt];
sum[rt<<1] += (k-h)*root[rt];///此处如h 和(k-h)弄反会wrong answer。因为左区间在k为奇数的情况下要比有区间大1
sum[rt<<1|1] += h*root[rt];
root[rt] = 0;
}
}
void build( int l, int r, int rt )
{
if( l == r )
{
sum[rt] = tree[l];
return ;
}
int m = (l+r)>>1;
build( lson );
build( rson );
pushup( rt );
}
void update( int a, int b, int c, int l, int r, int rt)
{
if( a <= l && b >= r )
{
root[rt] += c;
sum[rt] += (LL)c*(r-l+1);
return ;
}
pushdown(rt,(r-l+1));
int m = ( l+r )>> 1;
if( a <= m ) update( a , b, c, lson );
if(b > m ) update( a, b, c, rson );
pushup( rt );
}
LL query( int left, int right, int l, int r, int rt)
{
if( left <= l && right >= r) return sum[rt];
pushdown( rt , (r-l+1) );
int m = ( l+r )>>1;
LL s=0;
if(left<=m) s += query(left,right,lson);
if(right>m) s += query(left,right,rson);
return s;
}
int main()
{
int n,Q;
while(scanf("%d%d",&n,&Q)!=EOF)
{
memset(root,0,sizeof(root));
memset(sum,0,sizeof(sum));
for(int i=1; i<=n; i++)
{
scanf("%lld",&tree[i]);
}
build( 1, n, 1 );
char ch[2];
for(int i=1; i<=Q; i++)
{
scanf("%s",ch);
if(ch[0]=='Q')
{
int x,y;
scanf("%d%d",&x,&y);
printf("%lld\n",query(x,y,1,n,1));
}
else
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
update(a,b,c,1,n,1);
}
}
}
return 0;
}