Chinaunix首页 | 论坛 | 博客
  • 博客访问: 531776
  • 博文数量: 118
  • 博客积分: 3995
  • 博客等级: 中校
  • 技术积分: 1276
  • 用 户 组: 普通用户
  • 注册时间: 2005-11-15 12:15
文章分类

全部博文(118)

文章存档

2014年(1)

2013年(1)

2010年(6)

2009年(27)

2008年(10)

2007年(33)

2006年(38)

2005年(2)

我的朋友

分类:

2009-11-19 17:21:24

树状数组的详细讲解参照 http://fqq11679.blog.hexun.com/21722866_d.html

/*
 * 顺序给定n个数, 多次对这n个数进行两中操作
 * 1. 对第k个数进行加操作;
 * 2. 求前k项的和
 *
 * 使用树状数组
 * */


#include <stdio.h>

#define lowbit(x) ((x) & ((x) ^ (x-1)))
void add(int *C, int n, int pos, int v);


/* 初始化 */
int *init_C(int *A, int n)
{
    int *C;
    int i;

    if ((C=(int*)malloc(sizeof(int)*(n+1))) == NULL) exit(1);
    memset(C,0,sizeof(int)*(n+1));
    
    for (i=1; i<=n; i++) {
        add(C, n, i, A[i]);
    }
    return C;
}

/* 对某个元素进行加操作 */
void add(int *C, int n, int p, int v)
{
    while (p <= n) {
        C[p] += v;
        p += lowbit(p);
    }
}

/* 求前p项的和 */
int sum(int *C, int n, int p)
{
    int ret;

    ret = 0;
    while (p > 0) {
        ret += C[p];
        p -= lowbit(p);
    }
    return ret;
}


测试
int main()
{
    int A[] = {0,1,2,3,4,5,6,7,8,9};
    int n,i;
    int *C;

    n = 9;
    C = init_C(A, n);
    for (i=1;i<=n;i++)
        printf("%d\n", C[i]);
    printf("C%d: %d\n", n, sum(C,n,5));
    printf("C%d: %d\n", n, sum(C,n,9));
}


阅读(1169) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

朝花夕拾2009-11-20 10:09:14

http://www.nocow.cn/index.php/%E6%A0%91%E7%8A%B6%E6%95%B0%E7%BB%84

朝花夕拾2009-11-20 10:03:56

lowbit(x) 就是求x的二进制表示从最低位的1及其后面的0所表示的数 比如6,二进制110, 那么lowbit(6) = (10)2 = 2 比如8,二进制1000,那么lowbit(8) = (100)2 = 8 求最低位的1及其后面的0所表示的数值,可以 1. 使用 NOT x,先把最低位的1及其后面的零取反,然后再加1,他们又变回原值,高位不变;这样做的结果就是把让最低位1及其后面的0保持不变,其它位取反 2. x & (NOT x +1),就是lowbit(x) 由于NOT x +1 就是二进制补码的 -x,所以 lowbit(x) = x & (-x)