线段树
来源:互联网 发布:微博来自mac客户端 编辑:程序博客网 时间:2024/05/01 20:38
线段树的构造
线段树是一棵二叉树,他的每个节点包含了两个额外的属性start和end用于表示该节点所代表的区间。start和end都是整数,并按照如下的方式赋值:
- 根节点的 start 和 end 由 build 方法所给出。
- 对于节点 A 的左儿子,有 start=A.left, end=(A.left + A.right) / 2。
- 对于节点 A 的右儿子,有 start=(A.left + A.right) / 2 + 1, end=A.right。
- 如果 start 等于 end, 那么该节点是叶子节点,不再有左右儿子。
实现一个 build 方法,接受 start 和 end 作为参数, 然后构造一个代表区间 [start, end] 的线段树,返回这棵线段树的根。
/** * Definition of SegmentTreeNode: * class SegmentTreeNode { * public: * int start, end; * SegmentTreeNode *left, *right; * SegmentTreeNode(int start, int end) { * this->start = start, this->end = end; * this->left = this->right = NULL; * } * } */class Solution {public: /** *@param start, end: Denote an segment / interval *@return: The root of Segment Tree */ SegmentTreeNode * build(int start, int end) { // write your code here if (start > end) return NULL; SegmentTreeNode* node = new SegmentTreeNode(start, end); if (start != end) { int mid = start + (end - start) / 2; node->left = build(start, mid); node->right = build(mid+1, end); } return node; }};
线段树的查询
对于一个有n个数的整数数组,在对应的线段树中, 根节点所代表的区间为0-n-1, 每个节点有一个额外的属性max,值为该节点所代表的数组区间start到end内的最大值。
为SegmentTree设计一个 query 的方法,接受3个参数root, start和end,线段树root所代表的数组中子区间[start, end]内的最大值。
class Solution {public: /** *@param root, start, end: The root of segment tree and * an segment / interval *@return: The maximum number in the interval [start, end] */ int query(SegmentTreeNode *root, int start, int end) { // write your code here if (root->start == start && root->end == end) return root->max; int leftmax = 1<<31, rightmax = 1<<31; int mid = root->start + (root->end - root->start) / 2; // left half part if (start <= mid) { if (mid < end) { leftmax = query(root->left, start, mid); } else { leftmax = query(root->left, start, end); } } // right half part if (mid < end) { if (start <= mid) { rightmax = query(root->right, mid+1, end); } else { rightmax = query(root->right, start, end); } } return max(leftmax, rightmax); }};
线段树的修改
对于一棵 最大线段树, 每个节点包含一个额外的 max 属性,用于存储该节点所代表区间的最大值。
设计一个 modify 的方法,接受三个参数 root、 index 和 value。该方法将 root 为跟的线段树中 [start, end] = [index, index] 的节点修改为了新的 value ,并确保在修改后,线段树的每个节点的 max 属性仍然具有正确的值。
class Solution {public: /** *@param root, index, value: The root of segment tree and *@ change the node's value with [index, index] to the new given value *@return: void */ void modify(SegmentTreeNode *root, int index, int value) { // write your code here if (root->start == index && root->end == index) { root->max = value; return ; } int mid = root->start + (root->end - root->start) / 2; if (root->start <= index && index <= mid) { modify(root->left, index, value); } if (mid < index && index <= root->end) { modify(root->right, index, value); } root->max = max(root->left->max, root->right->max); }};
区间最小数
给定一个整数数组(下标由 0 到 n-1,其中 n 表示数组的规模),以及一个查询列表。每一个查询列表有两个整数 [start, end]。 对于每个查询,计算出数组中从下标 start 到 end 之间的数的最小值,并返回在结果列表中。
/** * Definition of Interval: * classs Interval { * int start, end; * Interval(int start, int end) { * this->start = start; * this->end = end; * } */class Solution { public: struct Node { Node* left, * right; int start, end, min; Node(int start, int end) { this->start = start; this->end = end; left = right = NULL; min = 1<<30; } }; Node* build(int start, int end) { if (start > end) return NULL; Node* root = new Node(start, end); if (start != end) { int mid = (start + end) / 2; root->left = build(start, mid); root->right = build(mid+1, end); } return root; } int query(Node* root, int start, int end) { if (root->start == start && root->end == end) return root->min; int leftmin = 1<<30, rightmin = leftmin; int mid = (root->start + root->end) / 2; if (start <= mid) { if (mid < end) { leftmin = query(root->left, start, mid); } else { leftmin = query(root->left, start, end); } } if (mid < end) { if (start <= mid) { rightmin = query(root->right, mid+1, end); } else { rightmin = query(root->right, start, end); } } return min(leftmin, rightmin); } void modify(Node* root, int index, int value) { if (root->start == index && root->end == index) { root->min = value; return ; } int mid = (root->start + root->end) / 2; if (root->start <= index && index <= mid) { modify(root->left, index, value); } if (mid < index && index <= root->end) { modify(root->right, index, value); } root->min = min(root->left->min, root->right->min); } /** *@param A, queries: Given an integer array and an query list *@return: The result list */ vector<int> intervalMinNumber(vector<int> &A, vector<Interval> &queries) { // write your code here vector<int> ret; if (A.size() == 0) return ret; Node* root = build(0, A.size()-1); for (int i=0; i<A.size(); i++) modify(root, i, A[i]); for (int i=0; i<queries.size(); i++) { ret.push_back(query(root, queries[i].start, queries[i].end)); } return ret; }};
1 0
- 线段树?线段树!
- 线段树?线段树!
- 线段_线段树
- 线段_线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- Volley学习笔记
- MYTH WAR's blog
- sheet1.hpyerlinks.add添加超链接,提取超链接的地址
- TCP、http的keepalive
- 操作系统调度算法(上)
- 线段树
- c#遍历文件夹和文件
- java多线程
- hdu 1568 Fibonacci
- QDUOJ 39 - 签到题(线段树)
- React和Redux的连接react-redux
- 杭电1213How Many Tables
- ios 数组里面的对象都执行一个方法
- GetLastError简介及返回值列表