POJ 3468 – A Simple Problem with Integers

Advanced Data Structures :: Segment Tree


Description

输入一个数列 {A1, A2, … , An} ,对其进行一系列操作:

  • Q a b 表示,询问一段连续的数列(从Aa到Ab)之和,并且输出。
  • C a b c 表示,修改一段连续的数列(从Aa到Ab),让他们自增c。


Type

Advanced Data Structures :: Segment Tree

Advanced Data Structures :: Binary Indexed Tree


Analysis

经典的线段树或数状数组的题目,要求能够成段更新。

利用线段树做延迟标记的时候,记得应该让延迟标记的值自增,而不是直接赋值。

且这题结果可能大于int,应使用long long


Solution

1. Segment Tree

// POJ 3468
// A Simple Problem with Integers
// by A Code Rabbit

#include <cstdio>

#define LSon(x) ((x) << 1)
#define RSon(x) ((x) << 1 | 1)

const int MAXN = 100002;
const int ROOT = 1;

struct Seg {
    long long w;
    int flag;
};

struct SegTree {
    Seg node[MAXN << 2];
    void Update(int pos) { node[pos].w = node[LSon(pos)].w + node[RSon(pos)].w; }
    void Build(int l, int r, int pos) {
        node[pos].flag = 0;
        if (l == r) {
            scanf("%lld", &node[pos].w);
            return;
        }
        int m = l + r >> 1;
        Build(l, m, LSon(pos));
        Build(m + 1, r, RSon(pos));
        Update(pos);
    }
    void Push(int l, int r, int pos) {
        Seg& father = node[pos];
        Seg& lson = node[LSon(pos)];
        Seg& rson = node[RSon(pos)];
        int len = r + 1 - l;
        if (father.flag) {
            lson.flag += father.flag;
            rson.flag += father.flag;
            // Pay attention to changing int into long long.
            lson.w += (long long)father.flag * (len - (len >> 1));
            rson.w += (long long)father.flag * (len >> 1);
            father.flag = 0;
        }
    }
    void Modify(int l, int r, int pos, int x, int y, int z) {
        if (x <= l && r <= y) {
            int len = r + 1 - l;
            // Pay attention to changing int into long long.
            node[pos].w += (long long)z * len;
            node[pos].flag += z;
            return;
        }
        Push(l, r, pos);
        int m = l + r >> 1;
        if (x <= m) Modify(l, m, LSon(pos), x, y, z);
        if (y > m) Modify(m + 1, r, RSon(pos), x, y, z);
        Update(pos);
    }
    long long Query(int l, int r, int pos, int x, int y) {
        if (x <= l && r <= y) return node[pos].w;
        Push(l, r, pos);
        int m = l + r >> 1;
        long long res = 0;
        if (x <= m) res += Query(l, m, LSon(pos), x, y);
        if (y > m) res += Query(m + 1, r, RSon(pos), x, y);
        return res;
    }
};

int n, q;
char ch;
int a, b, c;

SegTree tree;

int main() {
    while (scanf("%d%d", &n, &q) != EOF) {
        tree.Build(1, n, ROOT);
        while (q--) {
            getchar();
            scanf("%c", &ch);
            if (ch == 'Q') {
                scanf("%d%d", &a, &b);
                printf("%lld\n", tree.Query(1, n, ROOT, a, b));
            } else
            if (ch == 'C') {
                scanf("%d%d%d", &a, &b, &c);
                tree.Modify(1, n, ROOT, a, b, c);
            }
        }
    }

    return 0;
}

2. Binary Indexed Tree
// POJ 3468
// A Simple Problem with Integers
// by A Code Rabbit

#include <cstdio>
#include <cstring>

const int MAXN = 100002;

struct Bit {
    long long c[MAXN];
    int n;
    void Init(int x) { memset(c, 0, sizeof(c)); n = x; }
    void Add(int x, long long y) {
        while (x <= n) { c[x] += y; x += x & -x; }
    }
    long long Sum(int x) {
        long long res = 0;
        while (x > 0) { res += c[x]; x -= x & -x; }
        return res;
    }
};

struct NewBit {
    Bit b1, b2;
    void Init(int x) { b1.Init(x); b2.Init(x); }
    void Add(int x, int y, long long z) {
        b1.Add(x, z);
        b1.Add(y + 1, -z);
        b2.Add(x, z * x);
        b2.Add(y + 1, -z * (y + 1));
    }
    long long Sum(int x) { return (x + 1) * b1.Sum(x) - b2.Sum(x); }
};

int n, q;
int a, b, c;
char ch;
NewBit bit;

int main() {
    scanf("%d%d", &n, &q);
    bit.Init(n);
    for(int i = 0; i < n; i++) {
        scanf("%d", &a);
        bit.Add(i + 1, i + 1, a);
    }
    while (q--) {
        getchar();
        scanf("%c", &ch);
        if(ch == 'Q'){
            scanf("%d%d", &a, &b);
            printf("%lld\n", bit.Sum(b) - bit.Sum(a - 1));
        } else {
            scanf("%d%d%d", &a, &b, &c);
            bit.Add(a, b, c);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值