HDOJ 1166 敌兵布阵

线段树的入门题,数组代替树;

线段树是一种完全二叉树,主要操作有建树、修改节点、区间询问(最大值或者和等),由于采用二叉树结构,对一个结点的操作复杂为 logn;

这里建树、修改和询问操作没有采用递归方式,主要是利用了线段树也是完全二叉树的特点,因此可以直接根据要查看节点的编号(1..n)求得其对应在树中的编号,就可以直接进行操作,而不需要递归来实现。

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

# define N (1 << 17)
# define M ((1 << 16) )

int segSum[N];

void initTree(void)
{
    segSum[0] = 0;

    memset(segSum, 0, sizeof(segSum));
}

int query(int Left, int Right)
{
    int ret;

    ret = 0;
    Left += M-1, Right += M+1;
    while ((Right ^ Left) != 1)
    {        
        if ((Left&0x1) == 0) ret += segSum[Left+1];
        if ((Right&0x1) == 1) ret += segSum[Right-1];
        Left >>= 1, Right >>= 1;
    }

    return ret;
}

void add(int i, int dx)
{
    int p;

    p = i + M;
    while (p != 0)
    {
        segSum[p] += dx;
        p >>= 1;
    }
}

int main()
{
    char buf[10];
    int T, n, i, j, x, k;

    scanf("%d", &T);
    for (k = 1; k <= T; ++k)
    {
        initTree();
        scanf("%d", &n);
        for (i = 1; i <= n; ++i)
        {
            scanf("%d", &x);
            add(i, x);
        }
        printf("Case %d:\n", k);
        while (1)
        {
            scanf("%s", buf);
            if (buf[0] == 'E') break;
            scanf("%d%d", &i, &j);
            if (buf[0] == 'Q') printf("%d\n", query(i, j));
            else if (buf[0] == 'A') add(i, j);
            else if (buf[0] == 'S') add(i, -j);
        }
    }

    return 0;
}

//

原文地址:https://www.cnblogs.com/JMDWQ/p/2581677.html