您的位置:首页 > 其它

POJ-3468-A Simple Problem with Integers (线段树 区间求和)

2014-08-12 21:15 453 查看
A Simple Problem with Integers

Description

You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is
to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.

The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.

Each of the next Q lines represents an operation.

"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.

"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

Sample Output
4
55
9
15


一天了。。。研究这么点东西。。。sad。。。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>

using namespace std;
#define LL long long

const int inf = 111111;
LL add[inf << 2];
LL sum[inf << 2];
LL anst;

void pushup (int ii)//区间向上更新
{
    sum[ii] = sum[ii * 2] + sum[ii * 2 + 1];
}

void pushdown (int ii,int m)//区间下放
{
    if ( add[ii] )
    {
        add[ii * 2 ] += add[ii];
        add[ii * 2 + 1] += add[ii];
        sum[ii * 2] += add[ii] * (m-(m >> 1));
        sum[ii * 2 + 1] +=  add[ii] * (m >> 1);//因为在建树的时候右边总是 m>>1    左边不确定有多少个 
        add[ii] = 0;
    }
}

void build (int ii,int l,int r)
{
    add[ii] = 0;
    if ( l == r )
    {
        scanf ("%I64d",&sum[ii]);
        return ;
    }
    int m = ( l + r ) >> 1;
    build (ii * 2,l,m);
    build (ii * 2 + 1,m + 1,r);
    pushup (ii);
}

LL query (int ii,int l,int r,int a,int b)
{
    if ( a <= l && r <= b)
    {
        return sum[ii];
    }
    pushdown (ii,r - l + 1);
    int m = (l + r)>>1;
     LL ans = 0;
    if ( a <= m )
        ans += query (ii * 2,l,m,a,b);
    if ( b > m)
        ans += query (ii * 2 + 1,m + 1,r,a,b);
    return ans;
}

void updata (int ii,int l,int r,int a,int b,int z)
{
    if ( a <= l && r <= b)//区间被完全覆盖
    {
        add[ii] += z;
        sum[ii] +=  (LL) ((r - l + 1) * z);//当前节点的值 也就是此节点以下值得和 都加上z   r - l + 1就代表区间长度
        return ;
    }
    pushdown (ii,r - l + 1);
    int m = ( r + l )>>1;
    if ( a <= m )
        updata (ii * 2,l,m,a,b,z);
    if ( b > m)
        updata ( ii * 2 + 1,m + 1,r,a,b,z);
    pushup (ii);
}

int main ()
{
    int n,q;
    scanf ("%d%d",&n,&q);
    build (1,1,n);
    while (q --)
    {
        char op[5];
        int a,b,c;
        scanf ("%s",op);
        if ( op[0] == 'Q')
        {
            scanf ("%d%d",&a,&b);
            anst = query (1,1,n,a,b);//从1号节点开始  树的区间从1到n  待查询区间 从a到b
            printf ("%I64d\n",anst);
        }
        else
        {
            scanf ("%d%d%d",&a,&b,&c);
            updata (1,1,n,a,b,c);//从1号节点开始 树的区间 待更新区间  更新值
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐