HDOJ 1166 - 敌兵布阵

Advanced Data Structures :: Segment Tree


Description

敌人的军队驻扎在各个营地里,告诉你各个营地里有多少人,

请计算从第i个营地到第j个营地一共有多少人。

同时,敌人营地里的人数可能发生改变,因此会有三种操作——增加、减少、询问。

输出每次询问的结果。


Type

Advanced Data Structures :: Segment Tree

Advanced Data Structures :: Binary Indexed Tree


Analysis

经典的线段树题目, 也是经典的树状数组的题目。

可以用线段树和树状数组两种方法来实现。

数状数组和线段树相比,复杂度相当,但是常数更小,速度更快、空间消耗更小,且编程复杂度较低。

但数状数组没有线段树功能那么的强大,例如无法求解RMQ问题。


Solution

1. Segment Tree

// HDOJ 1166
// 敌兵布阵
// by A Code Rabbit

#include <cstdio>
#include <cstring>

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

const int MAXN = 50002;
const int ROOT = 1;

struct Seg{
    int w;
};

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) {
        if (l == r) { scanf("%d", &node[pos].w); return; }
        int m = l + r >> 1;
        Build(l, m, LSon(pos));
        Build(m + 1, r, RSon(pos));
        Update(pos);
    }
    void Modify(int l, int r, int pos, int x, int y) {
        if (l == r) { node[pos].w += y; return; }
        int m = l + r >> 1;
        if (x <= m) Modify(l, m, LSon(pos), x, y);
        else Modify(m + 1, r, RSon(pos), x, y);
        Update(pos);
    }
    int Query(int l, int r, int pos, int x, int y) {
        if (x <= l && r <= y) return node[pos].w;
        int m = l + r >> 1;
        int 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;
char cmd[20];
int x, y;

SegTree tree;

int main() {
    int tot_case = 0;
    scanf("%d", &tot_case);
    for (int t = 0; t < tot_case; t++) {
        scanf("%d", &n);
        tree.Build(1, n, ROOT);
        printf("Case %d:\n", t + 1);
        while (1) {
            getchar();
            scanf("%s", cmd);
            if (!strcmp(cmd, "Add")) {
                scanf("%d%d", &x, &y);
                tree.Modify(1, n, ROOT, x, y);
            } else
            if (!strcmp(cmd, "Sub")) {
                scanf("%d%d", &x, &y);
                tree.Modify(1, n, ROOT, x, -y);
            } else
            if (!strcmp(cmd, "Query")) {
                scanf("%d%d", &x, &y);
                printf("%d\n", tree.Query(1, n, ROOT, x, y));
            } else
            if (!strcmp(cmd, "End")) {
                break;
            }
        }
    }

    return 0;
}

2. Binary Indexed Tree
// HDOJ 1166
// 敌兵布阵
// by A Code Rabbit

#include <cstdio>
#include <cstring>

const int MAXN = 50002;

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

int n;
int a[MAXN];
char command[10];
int p, q;
Bit bit;

int main() {
    int tot_case;
    scanf("%d", &tot_case);
    for (int t = 0; t < tot_case; t++) {
        scanf("%d", &n);
        bit.Init(n);
        for (int i = 0; i < n; i++) {
            scanf("%d", &a[i]);
            bit.Add(i + 1, a[i]);
        }
        printf("Case %d:\n", t + 1);
        while (scanf("%s", command) && strcmp(command, "End") != 0) {
            scanf("%d%d", &p, &q);
            if (strcmp(command, "Add") == 0)
                bit.Add(p, q);
            else if (strcmp(command, "Sub") == 0)
                bit.Add(p, -q);
            else if (strcmp(command, "Query") == 0)
                printf("%d\n", bit.Sum(q) - bit.Sum(p - 1));
        }
    }

    return 0;
}

你可能感兴趣的:(HDOJ 1166 - 敌兵布阵)