树状数组
//树状数组类
class BITree
{//树状数组数值处理部分:1~BITree_num
//实际操作中建议数组开大一点
public:
BITree(int dim,int x,int y); //构造(维数,树状数组长度)
~BITree(); //析构
int lowbit(int x); //求最低位1对应值
//一维树状数组
void update_1(int i, int cal); //更新点求区间
void update_1(int pre, int last, int cal); //更新区间(差分原理),求点
int sum_pre_1(int i); //求前缀和(更新点)/求点(更新区间)
int sum_between_1(int pre, int last); //求区间和(更新点)
//二维树状数组
void update_2(int x, int y, int cal); //更新点
void update_2(int left, int right, int below, int top, int cal); //更新子矩阵(差分原理),求点
int sum_pre_2(int x, int y); //求前缀子矩阵
int sum_between_2(int left, int right, int below, int top); //求任意子矩阵
private:
int BITree_num_1; //一维树状数组长度
int BITree_num_x; //二维树状数组x轴长度
int BITree_num_y; //二维树状数组y轴长度
int BITree_dim; //树状数组维度
int* val_1; //一维树状数组
int** val_2; //二维树状数组
};
BITree::BITree(int dim,int x,int y)
{//构造函数
BITree_dim = dim; //树状数组维度
if (dim == 1)
{//构建一维树状数组参数列表:(1,num,0)
BITree_num_1 = x;
val_1 = new int[x];
memset(val_1, 0, sizeof(int)*BITree_num_1);
}
else
{//构建一维树状数组参数列表:(2,x,y)
BITree_num_x = x;
BITree_num_y = y;
val_2 = (int**)new int*[x];
for (int i = 0;i < BITree_num_x;i++)
val_2[i] = new int[y];
for (int i = 0;i < BITree_num_x;i++)
memset(val_2[i], 0, sizeof(int)*BITree_num_y);
}
}
BITree::~BITree()
{//析构函数
if (BITree_dim == 1)
{
delete[]val_1;
BITree_num_1 = 0;
}
else
{
for (int i = 0;i < BITree_num_x;i++)
delete[]val_2[i];
BITree_num_x = 0;
BITree_num_y = 0;
}
BITree_dim = 0;
}
int BITree::lowbit(int x)
{//返回二进制数最低位的1对应的数值
return x & (-x); //与运算
}
//一维树状数组
void BITree::update_1(int i, int cal)
{//原数组第i个元素加上cal,更新树状数组相关元素
//可直接用于树状数组的建立
for (;i <= BITree_num_1;i += lowbit(i))
val_1[i] += cal;
}
void BITree::update_1(int pre, int last, int cal)
{//更新区间(差分原理)
BITree::update_1(pre, cal);
cal = 0 - cal; //区间末端变为-cal
BITree::update_1(last+1, cal);
}
int BITree::sum_pre_1(int i)
{//求arry数组的前i项和
//val为树状数组地址
int sum = 0;
for (;i > 0;i -= lowbit(i)) //从后向前每次跳一个lowbit
sum += val_1[i];
return sum;
}
int BITree::sum_between_1(int pre, int last)
{//求原数组arry在区间[pre-last]的和
return sum_pre_1(last) - sum_pre_1(pre - 1);
}
//二维树状数组
void BITree::update_2(int x, int y, int cal)
{//当原数组A[x][y]+cal时,更新树状数组val
for (int i = x;i <= BITree_num_x;i += lowbit(i))
for (int j = y;j <= BITree_num_y;j += lowbit(j))
val_2[i][j] += cal;
}
void BITree::update_2(int left, int right, int below, int top, int cal)
{//更新子矩阵【left】【below】——【right】【top】+cal(差分原理)
update_2(left, below, cal);
update_2(right+ 1, top + 1, cal);
cal = 0 - cal;
update_2(left, top + 1, cal);
update_2(right + 1, below, cal);
}
int BITree::sum_pre_2(int x, int y)
{//求A[x][y]左上方的子矩阵A[1--x][1--y]的和
int sum = 0;
for (int i = x;i > 0;i -= lowbit(i))
for (int j = y;j > 0;j -= lowbit(j))
sum += val_2[i][j];
return sum;
}
int BITree::sum_between_2(int left, int right, int below, int top)
{//求矩阵A[left--right][below--top]的和
return sum_pre_2(right, top) - sum_pre_2(right, below - 1) - sum_pre_2(left - 1, top) + sum_pre_2(left - 1, below - 1);
}