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; }