参考:详解线段树
这里暂时不详解线段树了,等自己再明白点再写吧,板子是这样,就是和二叉树概念差不多。需要根据题目的需要,定义节点的值。
线段树模板【动态开点】
从刷题后的运行时间来看,耗时挺大,不知道什么原因导致,(是因为动态开点的原因吗)。
// 基于求「区间和」以及对区间进行「加减」的更新操作,且为「动态开点」
struct Node {
Node *left,*right;
int val,lazy;
Node():val(0),lazy(0),left(nullptr),right(nullptr){
}
};
const int N = 1e9;
Node *root = new Node();
void update(Node *node, int start, int end,int l, int r, int val) {
if(l<=start && r>=end) {
node->val += (end - start + 1) * val;
node->lazy += val;
return;
}
int mid = (start + end) >> 1;// 右移除2
pushDown(node, mid-start+1, end-mid);
if(l <= mid) update(node->left, start, mid, l, r, val); //[start,mid] [l,r] 有交集
if(r > mid) update(node->right, mid + 1, end, l, r, val); //[l,r] [mid+1,end] 有交集
pushUp(node);
}
void pushDown(Node *node, int leftNum, int rightNum) {
if(node->left==NULL) node->left = new Node();
if(node->right==NULL) node->right = new Node();
if(node->lazy==0) return; // 不需要向下更新
node->left->val += node->lazy * leftNum;
node->right->val += node->lazy * rightNum;
node->left->lazy += node->lazy;
node->right->lazy += node->lazy;
node->lazy = 0;
}
void pushUp(Node *node) {
node->val = node->left->val + node->right->val;
}
int query(Node *node, int start, int end, int l, int r) {
if(l<=start && r>=end) return node->val;
int mid = (start + end) >> 1, ans = 0;
pushDown(node, mid-start+1, end-mid);
if(l<=mid) ans += query(node->left, start, mid, l, r);
if(r>mid) ans += query(node->right, mid+1, end, l, r);
return ans;
}
729. 我的日程安排表 I
线段树版本400ms
class MyCalendar