模板:线段树(2)区间修改
2016-03-16 20:21
477 查看
好像叫做懒操作来着。。还是叫延迟修改更高大上一点吧
增加操作
设置操作
上面set操作的maintain貌似需要重写一下,等我找一道题目试一下再修改。
增加操作
//区间修改 /*两种操作 Add(L ,R ,v):把A[L],A[L+1],...,A[R]的值全部增加v Query(L ,R )计算子序列A[L],A[L+1],...,A[R]的元素和,最小值和最大值 */ //修改/查询的范围均为[y1,y2] //维护节点o,它对应区间[L,R] void maintain(int o, int l, int r) { int lc = o*2, rc = o*2+1; if(r > l) { //考虑左右子树 sumv[o] = sumv[lc] + sumv[rc]; minv[o] = min(minv[lc], minv[rc]); maxv[o] = max(maxv[lc], maxv[rc]); } minv[o] += addv[o]; maxv[o] += addv[o]; sumv[o] += addv[o] * (r-l+1);//考虑add操作 if(r==l) addv[o] = 0; } void update(int o, int l, int r) { int lc = o*2, rc = o*2+1; if(y1 <= l && r <= y2) { //递归边界 addv[o] += v; //累加边界的add值 } else { int m = l + (r-l)/2; if(y1 <= m) update(lc, l, m); if(y2 > m) update(rc, m+1, r); } maintain(o, l, r); //递归结束前重新计算本节点的附加信息 } int _min, _max, _sum; //全局变量,目前位置的最小值、最大值和累加值 void query(int o, int l, int r,int add){ //add为当前节点延迟修改值 if(y1 <= l && y2 >= r) { //递归边界:用边界区间的附加信息更新答案 _sum += sumv[o] + add * (r-l+1); _min = min(_min, minv[o] + add); _max = max(_max, maxv[o] + add); } else { //递归统计,累加参数add int m = l + (r-l)/2; if(y1 <= m) query(o*2, l, m, add + addv[o]); if(y2 > m) query(o*2+1, m+1, r, add + addv[o]); } }
设置操作
/*两种操作: Set(l, r, v): 把A[l],A[l+1],,...,A[r]的值全部修改为v(v>=0) Query(l, r): 计算子序列A[l],A[l+1],...,A[r]的元素和、最小值和最大值 */ void update(int o, int l, int r) { int lc = o*2, rc = o*2+1; if(y1 <= l && y2 >= r) { //标记修改 setv[o] = v; } else { pushdown(o); int m = l + (r-l)/2; if(y1 <= m) update(lc, l, m); else maintain(lc, l, m); if(y2 > m) update(rc, m+1, r); else maintain(rc, m+1, r); } maintain(o, l, r); } //标记传递 void pushdown(int o){ int lc = o*2, rc = o*2+1; if(setv[o] >= 0) { //本节点有标记才传递。 注意本题中set值非负,所以-1代表没有标记 setv[lc] = setv[rc] = setv[o]; setv[o] = -1; //消除本节点标记 } } void query(int o, int l, int r) { if(setv[o] >= 0) { //递归边界1: 有set标记 _sum += setv[o] * (min(r, y2)-max(l, y1)+1); _min = min(_min, setv[o]); _max = max(_max, setv[o]); } else if(y1 <= l && y2 >= r) { //递归边界2:边界区间 _sum += sumv[o]; _min = min(_min, setv[o]); _max = max(_max, setv[o]); } else { //递归统计 int m = l + (r-l)/2; if(y1 <= m) query(o*2, l, m); if(y2 > m) query(o*2+1, m+1, r); } }
上面set操作的maintain貌似需要重写一下,等我找一道题目试一下再修改。
相关文章推荐
- Leetcode:257. Binary Tree Paths(JAVA)
- 关于mini2440无法启动yaffs2的问题
- A-据说题目很水
- 阿里大鱼短信接口(Python3版)
- 密码学之路
- 游戏邮件系统
- ARM中MMU地址转换理解
- Lowest Common Ancestor of a Binary Search Tree
- 细谈CSS布局方式
- bzoj1303[CQOI2009]中位数图
- eclipse最有用快捷键整理
- poj 1979 Red and Black (简单裸搜索)
- linux 安装nginx
- Cogs 12 运输问题2 (有上下界网络流)
- Delphi 编译/链接过程
- Fibonacci 数列第 N项 O(logN)算法
- 1170: 非常男女(XCOJ 前缀和)
- CAS代理配置
- 白板编程浅谈——Why, What, How
- visual stdio 2010 安装包制作