训练日记-14

来源:互联网 发布:淘宝销量计算规则 编辑:程序博客网 时间:2024/06/05 01:11

       今天主要是结合例题更深入的理解了一下树状数组。其主要有三种基本模式:

       1.改变某一元素的值,查询某一区间内所有元素的和(单点更新,区间查询)。

#define Lowbit(p) (p&(-(p)))

//向上更新,向下求和

void Update(int *BIT,int p,int val)

{

    while ( p<=N )

    {

        BIT[p] += val;

        p += Lowbit(p);

    }

}

 

int GetSum(int *BIT,int p)

{

    int ret=0;

    while ( p>0 )

    {

        ret += BIT[p];

        p -= Lowbit(p);

    }

    return ret;

}

 

//向下更新,向上求和

void Update(int *BIT,int p,int val)

{

    while ( p>0 )

    {

        BIT[p] += val;

        p -= Lowbit(p);

    }

}

 

int GetSum(int *BIT,int p)

{

    int ret=0;

    while ( p<=N )

    {

        ret += BIT[p];

        p += Lowbit(p);

    }

    return ret;

}

2.把一个区间内的所有元素都加上一个值,查询某一个元素的值(区间更新,单点查询)。

#define Lowbit(p) (p&(-(p)))

//[l,r]中每个元素加上val

void _Update(int *BIT,int l,int r,int val)

{

    //调用的是模式一中的向上更新

    Update(BIT,l,val);

    Update(BIT,r+1,-val);

}

 

//询问p位置的数

int Querry(int BIT,int p)

{

    //调用的是模式一中的向下求和

    return GetSum(BIT,p);

}

3.把某一个区间内的所有元素都加上一个值,查询某一区间内所有元素的和(区间更新,区间查询)。 


#include <cstdio>

const int MAXN = 1024;

int B[MAXN], C[MAXN];

#define LOWBIT(x) ((x)&(-(x)))

void bit_update(int *a, int p, int d) {

for ( ; p && p < MAXN ; p += LOWBIT(p))

a[p] += d;

}

 

int bit_query(int *a, int p) {

int s = 0;

for ( ; p ; p -= LOWBIT(p))

s += a[p];

return s;

}

 

void bit_update2(int *a, int p, int d) {

for ( ; p ; p -= LOWBIT(p))

a[p] += d;

}

 

int bit_query2(int *a, int p) {

int s = 0;

for ( ; p && p < MAXN ; p += LOWBIT(p))

s += a[p];

return s;

}

 

inline void _insert(int p, int d) {

bit_update(B, p, p*d);

bit_update2(C, p-1, d);

}

 

inline int _query(int p) {

return bit_query(B, p) + bit_query2(C, p) * p;

}

 

inline void insert_seg(int a, int b, int d) {

_insert(a-1, -d);

_insert(b, d);

}

 

inline int query_seg(int a, int b) {

return _query(b) - _query(a-1);

}

 

int main() {

int com, a, b, c;

while (scanf("%d%d%d",&com,&a,&b) != EOF) {

a += 2; b += 2; //防止出现负数

if (com == 0) { //更新

scanf("%d",&c);

insert_seg(a, b, c);

} else { //查询

printf("%d\n",query_seg(a,b));

}

}

return 0;

}


        第一种为基本框架,第二种第三种都是根据第一种进行修改组合得到的,这三种只是基本框架,具体情况还要具体分析,根据具体要求灵活使用。