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;

}

//

你可能感兴趣的:(OJ)