POJ 3468 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
裸线段树区间更新的题, 但很恶心的一点是数据范围超int, 虽然定义了一部分long long最后还是wa, 找大神要了几组测试数据没毛病,断定是数据范围的问题, 但实在找不出哪出问题, 一气之下把int全部改为long long,3000msAC。。。。因为long long的原因可能有点慢了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100100
using namespace std;
struct seg
{
    long long val;//存区间权值
    long long addmark;//延时标记
}segtree[N * 4 + 10];
long long a[N * 4];
void build(long long node, long long left, long long right);//建树
void updata(long long node, long long _start, long long _end, long long left, long long right, long long add);//更新
long long query(long long node, long long _start, long long _end, long long left, long long right);//区间询问
void pushdown(long long node, long long left, long long right, long long mid);//将延时标记向下传递
int main()
{
    long long n, m;
    scanf("%lld%lld", &n, &m);
    for(long long i = 1; i <= n; i++)
    {
        scanf("%lld", &a[i]);
    }
    build(1, 1, n);
    char cmd;
    for(int i = 1; i <= m; i++)
    {
        scanf(" %c", &cmd);
        if(cmd == 'Q')
        {
            long long x, y;
            scanf("%lld%lld", &x, &y);
            long long ans = query(1, 1 , n, x, y);
            printf("%lld\n", ans);
        }
        else if(cmd == 'C')
        {
            long long x, y;
            long long z;
            scanf("%lld%lld%lld", &x, &y, &z);
            updata(1, 1, n, x, y, z);
        }
    }
    return 0;
}
void build(long long node, long long left, long long right)
{
    segtree[node].addmark = 0;//将每个延时标记初值为0
    if(left == right)
    {
        segtree[node].val = a[left];
        return;
    }
    long long mid = (left + right) >> 1;
    build(node * 2, left, mid);
    build(node * 2 + 1, mid + 1, right);
    segtree[node].val = segtree[node * 2].val + segtree[node * 2 + 1].val;
}
void updata(long long node, long long _start, long long _end, long long left, long long right, long long add)
{
    if(_start > right || _end < left)
    {
        return;
    }
    else if(_start >= left && _end <= right)
    {
        segtree[node].addmark += add;//更新此区间延时标记
        segtree[node].val += (_end - _start + 1) * add;//更新区间权值
        return;
    }
    long long mid = (_start + _end) >> 1;
    pushdown(node, _start, _end,mid);//每查询一个区间时顺带将延时标记向下传递,并清除此区间延时标记
    updata(node * 2, _start, mid, left, right, add);//更新左右子区间
    updata(node * 2 + 1, mid + 1, _end, left, right, add);
    segtree[node].val = segtree[node * 2].val + segtree[node * 2 + 1].val;

}
long long query(long long node, long long _start, long long _end, long long left, long long right)
{
    if(_start > right || _end < left)
    {
        return 0;
    }
    else if(_start >= left && _end <= right)
    {
        return segtree[node].val;
    }
    long long mid = (_start + _end) >> 1;
    pushdown(node, _start, _end, mid);//每次询问某个区间时顺便将此区间延时标记向下更新
    if(mid >= right)
    {
        return query(node * 2, _start, mid, left, right);
    }
    else if(mid < left)
    {
        return query(node * 2 + 1, mid + 1, _end, left, right);
    }
    long long q1 = query(node * 2, _start, mid, left, right);
    long long q2 = query(node * 2 + 1, mid + 1, _end, left, right);
    return q1 + q2;
}
void pushdown(long long node, long long left, long long right, long long mid)
{
    if(segtree[node].addmark != 0)
    {
        segtree[node * 2].val += (segtree[node].addmark * (mid - left + 1));//将延时标记更新到区间权值上
        segtree[node * 2 + 1].val += (segtree[node].addmark * (right - mid));
        segtree[node * 2].addmark += segtree[node].addmark;//更新子节点延时标记
        segtree[node * 2 + 1].addmark += segtree[node].addmark;
        segtree[node].addmark = 0;//清除父节点延时标记
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值