POJ 3468 A Simple Problem with Integers(线段树)

给出了一个序列,你需要处理如下两种询问。

"C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。

"Q a b" 询问[a, b]区间中所有值的和。

第一行包含两个整数N, Q。1 ≤ N,Q ≤ 100000.

第二行包含n个整数,表示初始的序列A (-1000000000 ≤ Ai ≤ 1000000000)。

接下来Q行询问,格式如题目描述。


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

这道题也比较简单,成段更新

体现了线段树的好处

不过要注意这里增加了两个方法  pushdown和pushup

pushup就是向上更新,也就是说父节点的和是两个子节点的和相加 从叶子节点累加上去到了根节点的话,最终根节点的和就是所有叶子节点的值加起来

有点像BOSS拿的钱就是各个小弟拿的钱加起来  就那么个意思~

pushdown就是向下更新,也就是说  比如你输入了 C 1 4 1也就是在第1个数到第4个数全部加1 

首先你就要找到1 到4 然后在1到4 下面的1 到 2 和 3 到 4 把要加的数也就是1 加上去 依次类推在 1 到 2 下面的1 和 2 加上1

那么结果就是你在 1 2 3 4这四个叶子节点中的值都加了1,在这里有两个要维护的域 一个是“加多少” tree[i].add ,另外一个是“加了之后是多少” tree[i].sum


在update中的

 if(A<=l&&B>=r)
    {
            tree[i].add+=C;
            tree[i].sum+=C*(r-l+1);
                return ;
    }
r-l+1是这段区间的长度也就是线段长度,比如上面所说的例子如果恰好是1 到 4 的话直接可以在 1 到4线段中加上 1*4=4 此次update就完成了

说到这里已经很清楚了,下面上代码:

#include<cstdio>
#define N 100005
int n,m;
long long num[N];
struct node
{
    int l,r;
    long long sum;
    long long add;
} tree[N<<2];
void pushup(int i)
{

    tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
}
void build(int l,int r,int i)
{
    tree[i].l=l;
    tree[i].r=r;
    if(l==r)
    {
        tree[i].sum=num[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,i<<1);
    build(mid+1,r,i<<1|1);
    pushup(i);
}
void pushdown(int rt,int dis)
{
    if(tree[rt].add)
    {
        tree[rt<<1].add+=tree[rt].add;
        tree[rt<<1|1].add+=tree[rt].add;
        tree[rt<<1].sum+=tree[rt].add*(dis-(dis>>1));
        tree[rt<<1|1].sum+=tree[rt].add*(dis>>1);
        tree[rt].add=0;
    }
}
void update(int A,int B,int C ,int l,int r,int i)
{
    if(A<=l&&B>=r)
    {
            tree[i].add+=C;
            tree[i].sum+=C*(r-l+1);
                return ;
    }
    pushdown(i,r-l+1);
    int mid=(l+r)>>1;
    if(A<=mid)update(A,B,C,l,mid,i<<1);
    if(B>mid)update(A,B,C,mid+1,r,i<<1|1);
    pushup(i);
}
long long query(int A,int B,int l,int r,int i)
{

    if(A<=l&&B>=r)
    {
        return tree[i].sum;
    }
    pushdown(i,r-l+1);
    long long ans=0;
    int mid=(l+r)>>1;
    if(A<=mid) ans+=query(A,B,l,mid,i<<1);
    if(B>mid) ans+=query(A,B,mid+1,r,i<<1|1);
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
        scanf("%I64d",&num[i]);

    build(1,n,1);
    while(m--)
    {
        char s[6];
        int a,b,c;
        scanf("%s",&s);
        if(s[0]=='C')
        {
            scanf("%d%d%d",&a,&b,&c);
            update(a,b,c,1,n,1);
        }
        else
        {
            scanf("%d%d",&a,&b);
            printf("%I64d\n",query(a,b,1,n,1));

        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dioml/article/details/50717404