目录

李超线段树

动态开点线段树

可持久化线段树(主席树)

启发式合并


luogu P3372线段树模板

#include<bits/stdc++.h>
#define MAXN 1000001
#define ll long long
using namespace std;
unsigned ll n,m,a[MAXN],ans[MAXN<<2],tag[MAXN<<2];
inline ll ls(ll x)
{return x<<1;
}
inline ll rs(ll x)
{return x<<1|1;
}
void scan()
{cin>>n>>m;for(ll i=1;i<=n;i++){scanf("%lld",&a[i]);}
}
inline void push_up(ll p)
{ans[p]=ans[ls(p)]+ans[rs(p)];
}
void build(ll p,ll l,ll r)
{tag[p]=0;if(l==r){ans[p]=a[l];return ;}ll mid=(l+r)>>1;build(ls(p),l,mid);build(rs(p),mid+1,r);push_up(p);
}
inline void f(ll p,ll l,ll r,ll k)
{tag[p]=tag[p]+k;ans[p]=ans[p]+k*(r-l+1);
}
inline void push_down(ll p,ll l,ll r)
{ll mid=(l+r)>>1;f(ls(p),l,mid,tag[p]);f(rs(p),mid+1,r,tag[p]);tag[p]=0;
}
inline void update(ll nl,ll nr,ll l,ll r,ll p,ll k)
{if(nl<=l&&r<=nr){ans[p]+=k*(r-l+1);tag[p]+=k;return ;}push_down(p,l,r);ll mid=(l+r)>>1;if(nl<=mid){update(nl,nr,l,mid,ls(p),k);}if(nr>mid) {update(nl,nr,mid+1,r,rs(p),k);}push_up(p);
}
ll query(ll q_x,ll q_y,ll l,ll r,ll p)
{ll res=0;if(q_x<=l&&r<=q_y){return ans[p];}ll mid=(l+r)>>1;push_down(p,l,r);if(q_x<=mid){res+=query(q_x,q_y,l,mid,ls(p));}if(q_y>mid) {res+=query(q_x,q_y,mid+1,r,rs(p)); }return res;
}
int main()
{ll a1,b,c,d,e,f;scan();build(1,1,n);while(m--){scanf("%lld",&a1);switch(a1){case 1:{scanf("%lld%lld%lld",&b,&c,&d);update(b,c,1,n,1,d);break;}case 2:{scanf("%lld%lld",&e,&f);printf("%lld\n",query(e,f,1,n,1));break;}}}return 0;
}

洛⾕ P3801 红⾊的幻想乡

n*m(n, m <= 105)的矩形区域中,进⾏如下两个操作: 1 x y : 蕾⽶莉亚站在坐标(x,y)的位置向四个⽅向释放⽆限的 红雾,当两个红雾相遇在同⼀点,则会沉降消失。 2 x1 y1 x2 y2 : 询问左上点为(x1,y1),右下点为(x2,y2)的矩 形范围内,被红雾遮盖的地区的数量

  • ⼀块n*m⼦矩阵中,施加 过红雾的⾏数为x、列数为y,则相遇抵消的点数 为x*y, 则红雾覆盖的点 数为

洛⾕ P2824 [HEOI2016/TJOI2016]排序

给出⼀个1到n的全排列,现在对这个全排列序列进⾏m次局部排序, 排序分为两种:
1:(0,l,r)表示将区间[l,r]的数字升序排序;
2:(1,l,r)表示将区间[l,r]的数字降序排序。
最后询问第q位置上的数字。

  • 二分q点的答案ans,原序列中小于等于ans的看成0,大于ans的看成1,这样区间排序就变成区间求和然后区间修改了

洛⾕ P4198 楼房重建

小 A 的楼房外有一大片施工工地,工地上有 N 栋待建的楼房。每天,这片工地上的房子拆了又建、建了又拆。他经常无聊地看着窗外发呆,数自己能够看到多少栋房子。

为了简化问题,我们考虑这些事件发生在一个二维平面上。小 A 在平面上 (0,0)(0,0)(0,0) 点的位置,第 iii 栋楼房可以用一条连接 (i,0) 和  的线段表示,其中 为第 i 栋楼房的高度。如果这栋楼房上任何一个高度大于 0 的点与 (0,0) 的连线没有与之前的线段相交,那么这栋楼房就被认为是可见的。

施工队的建造总共进行了 M 天。初始时,所有楼房都还没有开始建造,它们的高度均为 0。在第 i 天,建筑队将会将横坐标为 的房屋的高度变为 (高度可以比原来大—修建,也可以比原来小—拆除,甚至可以保持不变—建筑队这天什么事也没做)。请你帮小 A 数数每天在建筑队完工之后,他能看到多少栋楼房?

  • 首先,把所有的高度a[i]除以坐标i,得到从(0,0)望过去的直线斜率,判断楼与楼是否遮挡直接比较斜率大小即可
  • ans[k]表示节点k区间中的“单调递增序列”度(从左到右能看到的楼的数量)
  • 考虑由左右儿子的ans求出父亲节点的ans
  • 左儿子的ans都可以对父亲节点的ans做出贡献,而右儿子的ans则可能已经被左儿子中的楼遮挡,设左儿子的最大斜率为h,若能用求出节点k区间中大于h的楼的“单调递增序列”度,则

  • 那么如何写这个calc(k,h)函数呢?还是分情况讨论
  1. 若左子树中没有大于h的,则返回
  2. 若左子树中有大于h的,则全部对有贡献,右子树对ans[k]贡献的答案中都是大于h的楼房,则这个答案全部对有贡献,返回的就是
  • 这样调用一次函数复杂度是,总共调用次,总复杂度

李超线段树

用于解决区间添加一次函数、单点查询所有一次函数最大值的问题

洛⾕ P4097 [HEOI2013]Segment
要求在平⾯直⻆坐标系下维护两个操作:

  1. 在平⾯上加⼊⼀条线段。记第 i 条被插⼊的线段的标号为 i
  2. 给定⼀个数 k, 询问与直线 x = k 相交的线段中,交点最靠上的线段的编号。
  • 维护一个线段树,线段树每个节点维护对应区间的“优势线段”,即区间中点对应值最大的线段
  • 当在一个节点上添加一条线段时,分情况讨论:
  1. 当新线段完全被原优势线段覆盖时,新线段没用,不做修改
  2. 当新线段完全覆盖原优势线段时,原优势线段没用,将整个子树优势线段改为新线段
  3. 当两者有交点时,新优势线段为两者中中点对应值较大的一条,另一条递归添加到交点所在的一侧儿子中
  • 写着写着可以发现——这个标记可以永久化
  • 标记永久化:标记不进行下传,查询某一点时,取根到该叶子路径上所有标记的最优值

动态开点线段树

我们来观察一下普通线段树的左儿子和右儿子的表示方法

左儿子:p<<1

右儿子:p<<1|1

这样,虽然我们可以直接算出左右儿子,比较方便,但是,这样也浪费了大量的空间

链式储存法:即对一个节点维护其左右儿子的编号,指向它的左右儿子,这样,只有当访问某个节点时,我们才需要建立该节点,减小了空间

//单点修改
int insert(int k,int l,int r,int x)
{if(!k){k=++tot;}if(l==r){return sum[k]=a[l],k;}  if(x<=mid){ls[k]=insert(ls[k],l,mid,x);}else{re[k]=insert(re[k],mid+1,r,x);}sum[k]=sum[ls[k]]+sum[rs[k]];return k;
} 
//区间查询
int query(int k,int l,int r,int x,int y)
{if(x<=l&&r<=y){return sum[k];      }int mid=(l+r)>>1,res=0;if(x<=mid){res+=query(ls[k],l,mid,x,y);}if(y>mid){res+=query(rs[k],mid+1,r,x,y);}return res;
} 

可持久化线段树(主席树)

对于一个经过m次修改操作的线段树,可持久化线段树能维护其所有的m个历史版本

我们发现,每次修改只会修改线段树中的个节点,因此我们可以只对这个点开新节点,其余沿用旧树上的点

//单点修改
void update(int &o,int l,int r,int last,int p,int v)
{o=++tot;ls[o]=ls[last];rs[o]=rs[last];if(l==r){a[o]=v;return ; }   int m=(l+r)>>1;if(p<=m){update(ls[o],l,m,ls[last],p,v);}else{update(rs[o],m+1,r,rs[last],p,v);}
} 

查询无区别

静态区间第k小
给定n个数的序列,m次查询区间[l,r]的第k小值,n,m<=2e5

权值数组:一个数组a满足a[i]值为i的数的个数

权值线段树:维护权值数组的线段树

假如我们获得了[l,r]的权值线段树,查询时若左儿子区间和>=k则递归左儿子,若<k则递归右儿子即可

如何求[l,r]的权值线段树

可持久化线段树维护的权值线段树

即为[l,r]的权值线段树

//查询
int query(int s,int t,int l,int r,int x)
{if(l==r){return l;}int cnt=sum[ls[t]]-sum[ls[s]];if(cnt>=x){return query(ls[s],ls[t],l,mid,x);} else{return query(rs[s],rs[t],mid+1,r,x-cnt);}
} 

将两棵动态开点线段树合并到一起(对应位置相加)

如果一方对应位置没有点的话就用另一方的,都有就递归下去

复杂度

//合并
int merge(int p1,int p2,int l,int r)//表示将树p2的信息合并到树p1上
{if(!p1||!p2){return p1+p2;    } if(l==r){s[p1]=s[p1]+s[p2];return p1;}int mid=(l+r)>>1;ls[p1]=merge(ls[pl],ls[p2],l,mid);rs[p1]=merge(rs[p1],rs[p2],mid+1,r);s[p1]=s[ls[pl]]+s[rs[pl]];return p1;
} 

启发式合并

定义:将n个集合,合并集合A,B时,将较小的集合中的元素一个个插入到较大集合中,单次复杂度为

复杂度:

证明:每个数在跟比它所在集合更大的集合合并时会产生1的贡献,所在集合大小至少翻一倍,最多产生次贡献

黑科技

用于解决一些插入容易实现而删除难以实现的问题

用一个的代价将问题转化成只有插入

线段树分治

一个n个节点的图,m次操作,每次插入一条边,删除一条边。Q次查询,每次查询图是不是二分图。n,m<=1e5

  • 线段树分治实际上是一种维护时间区间的数据结构,同样是利用线段树的分治性,让复杂度保证在了级别
  • 开一棵维护操作时间的线段树,我们考虑如何维护一个操作影响的时间区间,假设一个操作影响的时间时[L,R],将其呈现在线段树上找这个询问所在时间点,把根到叶子路径上的所有影响计算一遍,就能得出这个询问的答案
  • 每次递归整棵线段树,到达一个节点时执行该节点上的所有操作,离开时撤销

7.30集训——线段树相关推荐

  1. 2018石中大集训线段树总结.。。。

    8/1 线段树练习总结--谢鹏宇 PS:题目见底部... A - I Hate It 就是一道模板题,但是还是提交了很多次,评测机可能对STD的max函数有点误解,用STD的就会错,然后自己手写了一个 ...

  2. 8.5 暑假集训——线段树篇

    是小潘学姐讲的这章,题目给的有些难度,很多没做出来,找了别的博客讲解的题刷 http://blog.csdn.net/metalseed/article/details/8039326 其中 hdu1 ...

  3. 数据结构二之线段树Ⅰ——Count Color,Hotel,Transformation,Tree Generator™

    普通的下标线段树 Count Color Hotel Transformation Tree Generator™ Count Color POJ2777 查询区间内颜色种类数,观察到颜色种类数只有3 ...

  4. 暑期集训5:并查集 线段树 练习题F:  HDU - 1166 ​​​​​​​

    2018学校暑期集训第五天--并查集 线段树 练习题F  --   HDU - 1166 敌兵布阵 C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A ...

  5. 暑期集训5:并查集 线段树 练习题G: HDU - 1754

    2018学校暑期集训第五天--并查集 线段树 练习题G  --   HDU - 1754 I Hate It 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.  这让 ...

  6. 暑期集训5:并查集 线段树 练习题B: HDU - 1213 ​​​​​​​

    2018学校暑期集训第五天--并查集 线段树 练习题B  --   HDU - 1213 How Many Tables Today is Ignatius' birthday. He invites ...

  7. 暑期集训5:并查集 线段树 练习题A:  HDU - 1232 ​​​​​​​

    2018学校暑期集训第五天--并查集 线段树 练习题A  --   HDU - 1232 畅通工程 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅 ...

  8. P3899 [湖南集训]谈笑风生(线段树合并)

    P3899 [湖南集训]谈笑风生 给定一颗以111号节点为根的树,如果a≠ba \neq ba​=b,且aaa是bbb的祖先,则aaa比bbb更厉害,如果a≠ba \neq ba​=b,且dis( ...

  9. 【地狱副本】数据结构之线段树Ⅲ——区间最值/赋值/修改/历史值操作(HDU5306,Tyvj 1518,【清华集训2015】V,HDU6315,HDU1828,POJ3162)

    文章目录 Gorgeous Sequence Tyvj 1518 CPU监控 [清华集训2015]V Naive Operations Picture Walking Race Gorgeous Se ...

最新文章

  1. 今天是2013年06月21日,博客之路开始了!
  2. 坦途与波折:我们需要什么样的人工智能?
  3. 计算机在识字教学中的应用,【多媒体技术论文】多媒体技术在小学识字教学中的应用(共3090字)...
  4. Web性能压力测试工具——Siege详解
  5. python中文编辑器推荐-推荐10款最好的Python开发编辑器
  6. 9.3 低秩矩阵分解-机器学习笔记-斯坦福吴恩达教授
  7. 基于matlab的频域辨识,基于Lab VIEW的控制系统频域分析研究
  8. 什么是 NIO? NIO 和 BIO、AIO 之间的区别是什么?NIO主要用来解决什么问题?
  9. 非集成搭建wampp环境
  10. 2019年,区块链不得不知的 9 件大事!
  11. java反编译有什么用处_Java反编译工具有什么用,Java反编译工具使用解析
  12. Android: eoeAndroid ~
  13. 趋势顶底(QSDD)----无未来函数
  14. 细丝菲涅尔衍射MATLAB,任意孔型菲涅尔衍射matlab仿真.docx
  15. Spring核心是什么
  16. SRRC型号核准的一点澄清-- 设备型产品的SRRC是强制性的,但模块型为非强制性的,有条件可参考性
  17. edge下载网络问题无法下载
  18. Todo Tree插件配置
  19. 运行edX Devstack
  20. 【互动媒体】结课作业第二部分:数据分析、可视化以及几个额外问题

热门文章

  1. mysql间隙锁可重入_关于mysql 间隙锁
  2. 终于把傅雷的《世界美术名作二十讲》看完了
  3. 细数T-BOX中TI的明星产品之 线性稳压器 | 第五节TPS7B7701-Q1:为车载应用保驾护航
  4. CSS display:table属性用法解析
  5. 《嵌入式系统》知识总结2:Cortex-M3处理器和STM32
  6. hostname修改
  7. 桌面删除快捷方式箭头之后不能锁定任务栏
  8. C语言学习笔记——使用字符数组和实型数组分别存储学生姓名和成绩,并通过对学生成绩的排序,按名次输出
  9. html里面的好看的动画效果
  10. 基于RNA测序技术的转录组从头拼接算法研究