樹狀陣列模板類
阿新 • • 發佈:2018-12-06
樹狀陣列
//樹狀陣列類 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); }