1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| *要求实现一种数据结构,使得它能够在O(logN)时间复杂度内动态维护一段序列:修改一个元素的权值,查询一段区间的最小(最大)值. * *线段树是一个二叉树,树上每个节点表示一段区间,每个节点的左右儿子分别是该节点表示的区间从中间断开后分成的左区间和右区间. *每个区间记录一个当前子树的最小/最大值Top[i]. *查询[a,b]区间的话也很简单,对于当前节点i,如果[a,b]能够完全覆盖i表示的区间,则直接返回Top[i],否则判断与左右区间是否有交 *递归进入访问,取两者之间的最大值即可. * *(假设这里维护的是最大值) *类: IntervalTree *成员函数: * IntervalTree(int size); 构造一颗维护区间[1..size]的线段树 * Int Query(int a, int b); 查询[a..b]区间内的最大值 * 复杂度: O(logN) * void Modify(int a, int d); 把第a个元素的值改成d * 复杂度: O(logN) * */
#define TREE_SIZE (i<<(20)) class IntervalTree{ private: int Cover[TREE_SIZE], Top[TREE_SIZE]; int size; int _Query(int a, int b, int l, int r, int Ind) { if (a <= l && b >= r) return Top[Ind]; int mid = (l+r) >> 1, ret = Cover[Ind]; if (a <= mid) ret = max(ret, _Query(a, b, l, mid, Ind << 1)); if (b > mid) ret = max(ret, _Query(a, b, mid+1, r, (Ind << 1)+1)); return ret; }
void _Modify(int a, int l, int r, int Ind, int d) { if (l == r && l == a) { Cover[Ind] = Top[Ind] = d; return; } int mid = (l+r) >> 1; if (a <= mid) _Modify(a, l, mid, Ind << 1, d); else _Modify(a, mid+1, r, (Ind<<1)+1, d); Top[Ind] = max(Top[Ind<<1], Top[(Ind<<1)+1]); }
public: IntervalTree() { memset(Cover, 0, sizeof(Cover)); memset(Top, 0, sizeof(Top)); size = (TREE_SIZE>>2) - 1; } IntervalTree(int size):size(size) { memset(Cover, 0, sizeof(Cover)); memset(Top, 0, sizeof(Top)); } int Query(int a, int b) { return _Query(a, b, 1, size, 1); } void Modify(int a, int d) { return _Modify(a, 1, size, 1, d); } };
|