hdu1166 敌兵布阵

简单的树状数组,利用树状数组求区间和,和修改元素后再求区间和的高效性,就是建树的时候比较费时费事。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>

using namespace std;

const int MAXN = 50010;

int a[MAXN];
int c[MAXN];
int N, T;

int lowbit(int x) {    ///求节点覆盖范围
    return x & (-x);
}

void change(int i, int x, int n) {   ///修改元素
    while (i <= n) {
        c[i] += x;
        i += lowbit(i);
    }
}

int Sum(int n) {
    int sum = 0;
    while (n > 0) {     ///从1开始到n求和
        sum += c[n];
        n -= lowbit(n);
    }
    return sum;
}

int f(int x, int y) {    ///求x到y区间的和
    if (x == 1) {
        return Sum(y);
    } else {
        return Sum(y) - Sum(x - 1);
    }
}

int main()
{
#if 0
    freopen("D:\\data.in", "r", stdin);
    freopen("D:\\data.out", "w", stdout);
#endif // 1
    int i, j;
    int cou = 0;
    int x, y;
    char str[20];
    while (~scanf("%d", &T)) {
        while (T--) {
            scanf("%d", &N);

            for (i = 1; i <= N; i++) {
                scanf("%d", &a[i]);
            }
            /*
            看网上很多人建树的时候是用递归方式的,此处用非递归方式直接在数组上建
            */
            for (i = 1; i <= N; i++) {
                if (i % 2 != 0) {    ///根据树状数组的结构,奇数直接存
                    c[i] = a[i];
                } else {
                    int sum = 0;
                    for (j = i; j >= i - lowbit(i) + 1; j--) {   ///偶数要看覆盖范围存
                        sum += a[j];
                    }
                    c[i] = sum;
                }
            }

            printf("Case %d:\n", ++cou);
            while (1) {
                scanf("%s", str);
                if (str[0] == 'E') break;
                scanf("%d%d", &x, &y);
                switch(str[0]) {
                    case 'A': change(x, y, N); break;
                    case 'S': change(x, -y, N); break;
                    case 'Q': printf("%d\n", f(x, y)); break;
                }
            }
        }
    }
    return 0;
}


你可能感兴趣的:(算法,ACM,树状数组,hduoj)