A Simple Problem with Integers(线段树+区间更新)

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

Hint
The sums may exceed the range of 32-bit integers.

题意:
给定一串数字,两种区间操作,询问区间和,区间内元素增加

思路:
线段树,区间更新

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

struct node
{
    long long left, right, lazy;
    long long data;
}tree[4000055];
long long a[1000055];

void build(long long l,long long r, long long k)    //普通方法建树即可
{
    tree[k].left = l;
    tree[k].right = r;
    tree[k].lazy = 0;
    if(l==r)
    {
        tree[k].data = a[l];
        return;
    }
    else
    {
        long long mid = (l + r) / 2;
        build(l, mid, 2 * k);
        build(mid+1, r, 2 * k + 1);
        tree[k].data = tree[2 * k].data + tree[2 * k + 1].data;
    }
}

void pushdown(long long k)     //把节点k的lazy值传给他的孩子,有需要时向下更新
{
    tree[2 * k].lazy += tree[k].lazy;
    tree[2 * k + 1].lazy += tree[k].lazy;
    tree[2 * k].data += (tree[2 * k].right - tree[2 * k].left + 1) * tree[k].lazy;
    tree[2 * k + 1].data += (tree[2 * k + 1].right - tree[2 * k + 1].left + 1) * tree[k].lazy;
    tree[k].lazy = 0;
}

long long ask(long long x, long long y, long long k)
{
    if(tree[k].lazy != 0) pushdown(k);      //看到节点,向下更新,
                      //否则如果走下面else的话,节点k的lazy传不到下面的小区间
    if(x <= tree[k].left && tree[k].right <= y) return tree[k].data;
    else
    {
        long long mid = (tree[k].left + tree[k].right) / 2;
        if(y <= mid) return ask(x, y, 2 * k);
        else if(x > mid) return ask(x, y, 2 * k + 1);
        else return ask(x, y, 2 * k) + ask(x, y, 2 * k + 1);
    }
}

void add(long long x, long long y, long long z, long long k)
{
    if(x <= tree[k].left && tree[k].right <= y)
    {
        tree[k].data += (tree[k].right - tree[k].left + 1) * z;        //data不要忘记乘区间元素个数
        tree[k].lazy += z;
        return;
    }
    else
    {
        if(tree[k].lazy != 0) pushdown(k);         //这里必须要pushdown的,不加会WA
                                        //只要看到新的区间,就pushdown一下好了,更新也没什么大坏处
        long long mid = (tree[k].left + tree[k].right) / 2;
        if(y <= mid) add(x, y, z, 2*k);
        else if(x > mid) add(x, y, z, 2*k+1);
        else
        {
            add(x, y, z, 2*k);
            add(x, y, z, 2*k+1);
        }
        tree[k].data = tree[2*k].data + tree[2*k+1].data;   //下面的节点更新完成,上面的自然要变
    }
}

int main()
{
    long long n, m, i, x, y, z;
    char c[10];
    scanf("%lld %lld", &n, &m);
    for(i=1;i<=n;i++)
    {
        scanf("%lld", &a[i]);
    }
    build(1, n, 1);
    while(m--)
    {
        scanf(" %s", c);
        if(c[0]=='Q')
        {
            scanf("%lld %lld", &x, &y);
            printf("%lld\n", ask(x, y, 1));
        }
        else if(c[0]=='C')
        {
            scanf("%lld %lld %lld", &x, &y, &z);
            add(x, y, z, 1);
        }
    }
    return 0;
}

WA了十多遍,
原因是一开始在判断是否要向下pushdown的时候写成了if(str[k].lazy>0),
当需要区间减小的时候进不去就WA了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值