poj 3468 A Simple Problem with Integers

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




你可能感兴趣的:(poj3468,线段树成段更新,线段树区间求和)