线段树模板(单点更新,区间更新,RMQ)
1.单点更新
说明
单点更新,区间求和(你问我单点求和??你就不会把区间长度设为0啊?)
• sum[]为线段树,需要开辟四倍的元素数量的空间。
• build()为建树操作
• update()为更新操作
• query()为查询操作
时间复杂度:O(nlogn)
使用方法
- build(1, n); 建立一个叶子节点为n个的线段树
- update(pos, val, 1, n); 更新树中下标为pos的叶子节点值增加val
- query(l, r, 1, n); 查询[l ,r]区间值之和
Tips
• 请注意update的目的是增减还是替换,根据情况修改update函数和pushup函数
• 建出来的树为空树,默认每个点值都为0,需要自行将值update上去,或者修改build中sum[rt]=0;为输入操作scanf(“%d”,sum+rt);
模版
// 有注释版
const int maxn=2005+5;
#define lson l,m,rt<<1 //预定子左树
#define rson m+1,r,rt<<1|1 //预定右子树
int sum[maxn<<2];//表示节点,需要开到最大区间的四倍
void pushup(int rt){
//对于编号为rt的节点,他的左右节点分别为rt<<1和rt<<1|1
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
//造树
void build(int l,int r,int rt=1){
//建树操作,生成一个区间为l~r的完全二叉树
//如果到底,则线段长度为0,表示一个点,输入该点的值
if (l==r) {
sum[rt]=0;
return;
}
//准备子树
int m=(l+r)>>1;
//对当前节点建立子树
build(lson);
build(rson);
//由底向上求和
pushup(rt);
}
//更新点和包含点的枝
void update(int pos,int val,int l,int r,int rt=1){
//pos为更新的位置 val为增加的值,正则加,负则减
//l r为区间的两个端点值
//触底,为一个点的时候,该节点值更新
if (l==r) {
sum[rt]+=val;
return;
}
int m = ( l + r ) >> 1;
if (pos<=m) //pos在左子树的情况下,对左子树进行递归
update(pos, val, lson);
else //pos在右子树的情况下,对右子树进行递归
update(pos, val, rson);
//更新包含该点的一系列区间的值
pushup(rt);
}
//查询点或区间
int query(int L,int R,int l,int r,int rt=1){
// L~R为被查询子区间 l~r为“当前”树的全区间
if (L<=l&&r<=R) //子区间包含“当前”树全区间
return sum[rt]; //返回该节点包含的值
int m=(l+r)>>1;
int res=0;
if (L<=m) //左端点在左子树内
res+=query(L, R, lson);
if (R>m) //右端点在右子树内
res+=query(L, R, rson);
return res;
}
2.区间更新
说明
区间更新,区间求和(你问我单点求和??你就不会把区间长度设为0啊?)
• sum[]为线段树,需要开辟四倍的元素数量的空间。
• build()为建树操作
• update()为更新操作
• query()为查询操作
时间复杂度:O(nlogn)
使用方法
- build(1, n); 建立一个叶子节点为n个的线段树
- update(l, r, val, 1, n); 更新线段树中[l, r]区间每个值都增加val
- query(l, r, 1, n); 查询[l ,r]区间值之和
Tips
• 请注意update的目的是增减还是替换,根据情况修改update函数和pushup函数
• 建出来的树为空树,默认每个点值都为0,需要自行将值update上去,或者修改build中sum[rt]=0;为输入操作scanf(“%d”,sum+rt);
模版
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 100005;
int add[maxn<<2],sum[maxn<<2];
void PushUp(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void PushDown(int rt,int m)
{
if (add[rt])
{
add[rt<<1] += add[rt];
add[rt<<1|1] += add[rt];
sum[rt<<1] += add[rt] * (m - (m >> 1));
sum[rt<<1|1] += add[rt] * (m >> 1);
add[rt] = 0;
}
}
void build(int l,int r,int rt=1)
{
add[rt] = 0;
if (l == r)
{
sum[rt]=0;
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L,int R,int c,int l,int r,int rt=1)
{
if (L <= l && r <= R)
{
add[rt] += c;
sum[rt] += c * (r - l + 1);
return ;
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
if (L <= m) update(L , R , c , lson);
if (m < R) update(L , R , c , rson);
PushUp(rt);
}
int query(int L,int R,int l,int r,int rt=1)
{
if (L <= l && r <= R)
{
return sum[rt];
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
int ret = 0;
if (L <= m) ret += query(L , R , lson);
if (m < R) ret += query(L , R , rson);
return ret;
}
3.RMQ
说明
RMQ:Range Minimum(Maximum) Query
• sum[]为线段树,需要开辟四倍的元素数量的空间。
• build()为建树操作
• update()为更新操作
• query()为查询操作
使用方法
- 根据情况修改RMQ的宏定义
- build(1, n); 建立一个叶子节点为n个的线段树
- update(pos, val, 1, n); 修改树中下标为pos的叶子节点值为val
- query(l, r, 1, n); 查询[l ,r]区间中的RMQ
Tips
• 建出来的树为空树,默认每个点值都为0,需要自行将值update上去,或者修改build中sum[rt]=0;为输入操作scanf(“%d”,sum+rt);
• RMQ为宏定义,请根据情况自行修改为max或者min,对应修改query中的res为-INF或者INF
const int maxn=2005+5;
#define RMQ max
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int sum[maxn<<2]={};
void pushup(int rt){
sum[rt]=RMQ(sum[rt<<1],sum[rt<<1|1]);
}
void build(int l,int r,int rt=1){
if (l==r){
sum[rt]=0;
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int pos,int val,int l,int r,int rt=1){
if (l==r) {
sum[rt]=val;
return;
}
int m=(l+r)>>1;
if (pos<=m) update(pos, val, lson);
else update(pos, val, rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt=1){
if (L<=l&&r<=R) return sum[rt];
int m=(l+r)>>1;
int res=-INF; //防负数的坑
if (L<=m) res=RMQ(res,query(L, R, lson));
if (R>m) res=RMQ(res,query(L, R, rson));
return res;
}
线段树模板(单点更新,区间更新,RMQ)的更多相关文章
- HDU 4348.To the moon SPOJ - TTM To the moon -可持久化线段树(带修改在线区间更新(增减)、区间求和、查询历史版本、回退到历史版本、延时标记不下放(空间优化))
To the moon Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
- POJ - 3264 线段树模板题 询问区间最大最小值
这是线段树的一个模板题,给出一串数字,然后询问区间的最大最小值. 这个其实很好办,只需把线段树的节点给出两个权值,一个是区间的最小值,一个是区间的最大值,初始化为负无穷和正无穷,然后通过不断地输入节点 ...
- hdu 1754 线段树(单点替换 区间最值)
Sample Input5 61 2 3 4 5Q 1 5 //1-5结点的最大值U 3 6 //将点3的数值换成6Q 3 4Q 4 5U 2 9Q 1 5 Sample Output5659 # i ...
- hdu 1166 线段树(单点增减 区间求和)
Sample Input1101 2 3 4 5 6 7 8 9 10Query 1 3Add 3 6Query 2 7Sub 10 2Add 6 3Query 3 10End Sample Outp ...
- poj3468 A Simple Problem with Integers(线段树模板 功能:区间增减,区间求和)
转载请注明出处:http://blog.csdn.net/u012860063 Description You have N integers, A1, A2, ... , AN. You need ...
- 线段树-sum/max/min/区间更新
写一个板子. #include <cstdio> #include <algorithm> using namespace std; +; #define ROOT 1, 1, ...
- 洛谷3372线段树模板题 对区间+k或者查询区间和
#include<bits/stdc++.h> using namespace std; typedef unsigned int ui; typedef long long ll; ty ...
- HDU 1754 I Hate It(线段树之单点更新 区间最值查询)
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- POJ 3468 A Simple Problem with Integers(线段树模板之区间增减更新 区间求和查询)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 140120 ...
- HDUOJ---1754 I Hate It (线段树之单点更新查区间最大值)
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
随机推荐
- C++ STL, sort用法。
在algorithm头文件中的sort可以给任意对象排序,包括内置类型和自定义类型,前提是定义了“<“运算符. sort(begin,end),表示一个范围,例如: #include" ...
- ACM学习历程—UESTC 1217 The Battle of Chibi(递推 && 树状数组)(2015CCPC C)
题目链接:http://acm.uestc.edu.cn/#/problem/show/1217 题目大意就是求一个序列里面长度为m的递增子序列的个数. 首先可以列出一个递推式p(len, i) = ...
- bzoj 2823: [AHOI2012]信号塔 最小圆覆盖
题目大意: 给定n个点,求面积最小的园覆盖所有点.其中\(n \leq 10^6\) 题解: 恩... 刚拿到这道题的时候... 什么???最小圆覆盖不是\(O(n^3)\)的随机增量算法吗????? ...
- 使用UIBezierPath添加投影效果
代码: ViewController.h #import <UIKit/UIKit.h> @interface ViewControlle ...
- bzoj 1711 Dining吃饭 —— 最大流
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1711 食物一列,牛拆点,饮料一列. 代码如下: #include<cstdio> ...
- 【转】Pro Android学习笔记(十一):了解Intent(中)
Intent的构成 Intent可以带有action,data(由URI表达),extra data(key/value map,键值对),指定的类名(成为component name).一个inte ...
- js之翻牌游戏中的一个深刻感悟
先“上菜”: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...
- 杂项:Code(开源资源)
ylbtech-杂项:Code(开源资源) 1.返回顶部 1.CSDN http://code.csdn.net/ 2.腾讯·开源 http://code.tencent.com/ 3. 4. 5. ...
- 初识Luajit
转自:http://www.cppblog.com/pwq1989/archive/2013/11/28/204487.html 大家可以从官网下载到源码(http://luajit.org/),也可 ...
- rails中一个窗体多个模型——fields_for
详细参考 http://railscasts.com/episodes/73-complex-forms-part-1中part-1.2.3部分 借助field_for可以生成表单来处理两个或更多模型 ...