树状数组之一
#include <iostream>
using namespace std;
int side;
int C[side]; //一维 C[1]-C[side]
int lowbit(int x)
{
return x&(-x);
}
void modify(int k,int m) //修改原数组a[k]中某一元素的值
{
while(k<=side)
{
C[k] += m;
k += lowbit(k);
}
}
//由于lowbit(0)=0,导致modify(0,m)发生死循环,所以树状数组中可能出现0时,我们都全部加1
int sum(int k) //求和,求原数组元素a[1]+a[2]+…a[k]的和
{
int sum = 0;
while(k>0)
{
sum += C[k];
k -= lowbit(k);
}
return sum;
}
//二维
int C[side][side];
int lowbit(int x)
{
return x&(-x);
}
void modify(int x,int y,int m)
{
int i=x,j;
while(i<=side)
{
j=y;
while(j<=side)
{
c[i][j]+=m;
j+=lowbit(j);
}
i+=lowbit(i);
}
}
int sum(int x,int y)
{
int i=x,j,sum=0;
while(i>0)
{
j=y;
while(j>0)
{
sum+=c[i][j];
j-=lowbit(j);
}
i-=lowbit(i);
}
return sum;
}
//令这棵树的结点编号为C1,C2...Cn。
//C1 = A1
//C2 = A1 + A2
//C3 = A3
//C4 = A1 + A2 + A3 + A4
//C5 = A5
//C6 = A5 + A6
//C7 = A7
//C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8
//设节点编号为x,那么这个节点管辖的区间为2^k(其中k为x二进制末尾0的个数)个元素。
//因为这个区间最后一个元素必然为Ax,所以很明显:Cn = A(n – 2^k + 1) + ... + An
//如何计算这个2^k呢
//int lowbit(int x)
//{
// return x&(-x); 与运算
//}
//2^k=x&(-x);
//-x的二进制数是x的补码(反码+1)比如
//x=1000 010, -x= 0111 101 +1 =0111 110
//x&(-x)=10 所以2^k=2