线段树(nb)
今天刚学习了线段树,赶紧趁热打了两遍模版
下面都是线段树的基本操作,这个板子是维护的区间中的最大值,当然修改change和build包括线段树中的data可以维护区间上的不同信息。
首先介绍一下线段树这种数据结构吧
线段树是一种基于分治思想的二叉树结构,用于在区间上进行信息的统计与维护
板子的一些默认信息
1、线段树的每个结点都代表一个区间。
2、线段树具有唯一的跟结点,代表的区间是整个统计范围,即[1~N]。
3、线段树的每个叶子结点都代表一个长度为1的元区间[x, x]。
4、 对于每个内部节点[l, r],它的左子结点是[l, mid], 右子结点是[mid + 1, r]
#include <iostream>
using namespace std;
//线段树是基于分治的思想实现的
//struct数组存储线段树
struct SegmentTree
{
int l, r;
int data;
}t[100 * 4];
int a[100];
//用线段树维护每个区间的最大值
void build(int p, int l, int r)
{
t[p].l = l, t[p].r = r;
if(r == l) {t[p].data = a[l]; return ;}
int mid = (l + r) >> 1;
build(p*2, l, mid);
build(p*2 + 1, mid + 1, r);
t[p].data = max(t[p * 2].data, t[p*2 + 1].data);
}
//调用入口
// build(1, 1, n);
//线段树的单点修改
void change(int p, int x, int v)
{
if(t[p].l == t[p].r) {t[p].data = v; return ;}//找到要修改的叶子结点
int mid = (t[p].l + t[p].r) >> 1;
if(x <= mid) change(p * 2, x ,v); //x属于左半区间
else change(p * 2 + 1, x, v); // 行属于右半区间
t[p].data = max(t[p * 2].data, t[p * 2 + 1].data);//从下往上更新信息
}
//线段树的区间查询
int ask(int p, int l, int r)
{
if(l <= t[p].l && r >= t[p].r) return t[p].data;
int mid = (t[p]. l + t[p].r) >> 1;
int val = -(1 << 30); //初始化为负无穷大
if(l <= mid) val = max(val, ask(p * 2, l, r));
if(r > mid) val = max(val, ask(p * 2 + 1, l ,r));
return val;
}
//调用出口 cout << ask(1, 1, r) << endl;
int main()
{
int n;cin >> n;
for(int i = 1; i <= n; ++ i) cin >> a[i];
build(1, 1, n);
cout << ask(1, 2, 3);
}
若要维护区间最大连续子段和
#include <iostream>
using namespace std;
//线段树是基于分治的思想实现的
//struct数组存储线段树
struct SegmentTree
{
int l, r;
int lmax, rmax, sum, data;
}t[100 * 4];
int a[100];
//用线段树维护每个区间的信息
void build(int p, int l, int r)
{
t[p].l = l, t[p].r = r;
if(r == l)
{
t[p].sum = a[l];
t[p].lmax = a[l];
t[p].rmax = a[l];
t[p].data = a[l];
return ;
}
int mid = (l + r) >> 1;
build(p*2, l, mid);
build(p*2 + 1, mid + 1, r);
t[p].lmax = max(t[p * 2].lmax, t[p * 2].sum + t[p * 2 + 1].lmax);
t[p].rmax = max(t[p * 2 + 1].rmax, t[p * 2 + 1].sum + t[p * 2].rmax);
t[p].data = max(t[p * 2].data, t[p * 2 + 1].data);
t[p].data = max(t[p].data, t[p * 2].rmax + t[p * 2 + 1].lmax);
}
//调用入口
// build(1, 1, n);
//线段树的单点修改
void change(int p, int x, int v)
{
if(t[p].l == t[p].r) {t[p].data = v; return ;}//找到要修改的叶子结点
int mid = (t[p].l + t[p].r) >> 1;
if(x <= mid) change(p * 2, x ,v); //x属于左半区间
else change(p * 2 + 1, x, v); // 行属于右半区间
//从下往上更新信息
t[p].sum = t[p * 2].sum + t[p * 2 + 1].sum;
t[p].lmax = max(t[p * 2].lmax, t[p * 2].sum + t[p * 2 + 1].lmax);
t[p].rmax = max(t[p * 2 + 1].rmax, t[p * 2 + 1].sum + t[p * 2].rmax);
t[p].data = max(t[p * 2].data, t[p * 2 + 1].data);
t[p].data = max(t[p].data, t[p * 2].rmax + t[p * 2 + 1].lmax);
}
//线段树的区间查询
int ask(int p, int l, int r)
{
if(l <= t[p].l && r >= t[p].r) return t[p].data;
int mid = (t[p]. l + t[p].r) >> 1;
int val = -(1 << 30); //初始化为负无穷大
if(l <= mid) val = max(val, ask(p * 2, l, r));
if(r > mid) val = max(val, ask(p * 2 + 1, l ,r));
return val;
}
//调用出口 cout << ask(1, 1, r) << endl;
int main()
{
int n;cin >> n;
for(int i = 1; i <= n; ++ i) cin >> a[i];
build(1, 1, n);
cout << ask(1, 1, 5);
}
可以看出我们只需要修改build和change部分即可,只需要加入我们想要维护区间的额外信息。
线段树也太好用了吧QWQ!!!
线段树(nb)的更多相关文章
- HDU4614【线段树。】
果然看了理解了一下大牛的代码然后自己敲结果果然有不少错误 回复说,线段树做为一种数据结构,最好以一种风格过一题裸的然后作为自己的模板.. 二分写的也很恶心哪 还有题目稍复杂一点的注定得推敲各种公式,不 ...
- HDU1394 Minimum Inversion Number(线段树OR归并排序)
Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java ...
- Luogu3732 [HAOI2017] 供给侧改革 【后缀数组】【线段树】【乱搞】
题目分析: 这道题我是乱搞的,因为他说$01$串是随机的. 那么我们可以猜测能够让LCP变大的地方很少.求出后缀数组之后可能让LCP变大的地方就等价于从大到小往height里动态加点同时维护这个点左右 ...
- BZOJ-2298|区间dp|线段树
problem a Description 一次考试共有n个人参加,第i个人说:"有ai个人分数比我高,bi个人分数比我低."问最少有几个人没有说真话(可能有相同的分数) Inpu ...
- Luogu5289 十二省联考2019字符串问题(后缀数组+拓扑排序+线段树/主席树/KDTree)
先考虑80分做法,即满足A串长度均不小于B串,容易发现每个B串对应的所有A串在后缀数组上都是一段连续区间,线段树优化连边然后判环求最长链即可.场上就写了这个. 100分也没有什么本质区别,没有A串长度 ...
- loj#2059. 「TJOI / HEOI2016」字符串 sam+线段树合并+倍增
题意:给你一个子串,m次询问,每次给你abcd,问你子串sa-b的所有子串和子串sc-d的最长公共前缀是多长 题解:首先要求两个子串的最长公共前缀就是把反过来插入变成最长公共后缀,两个节点在paren ...
- hdu-1394(线段树&逆序数的性质和求法)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题目大意: 给出一个序列,一对逆序数就是满足i<j&&a[i]>a[ ...
- 【BZOJ-4556】字符串 后缀数组+二分+主席树 / 后缀自动机+线段树合并+二分
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 657 Solved: 274[Su ...
- 字符串(tjoi2016,heoi2016,bzoj4556)(sam(后缀自动机)+线段树合并+倍增+二分答案)
佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为\(n\)的字符串\(s\),和\(m\)个问题.佳媛姐姐必须正确回答这\(m\)个问题, ...
- 【题解】洛谷P1198 [JSOI2008] 最大数(线段树)
洛谷P1198:https://www.luogu.org/problemnew/show/P1198 思路 一道水水的线段树 20分钟A掉 这道题只涉及到单点修改和区间查询 所以这道题甚至不用Laz ...
随机推荐
- 【线上技术分享】即构&MobTech袤博移动游戏开发者全能进阶沙龙
游戏行业的兴起与当前移动互联网用户碎片化.休闲化的生活特征密不可分,在用户旺盛的需求下,游戏行业迎来了绝佳的发展机遇,今年上半年已多款游戏DAU过亿. 市场的火爆也为游戏行业带来了异常激烈的竞争,加上 ...
- java使用apache.poi导出word文件
功能说明: 将试卷导出word,并可以打印,装订,效果图: 下面是实现代码: package com.xxxxx.business.course.utils; import com.alibaba.f ...
- 如何用IoT边缘连接器实现云端应用控制PLC?
本文分享自华为云社区<数字工厂深入浅出系列(十):IoT边缘连接器实现云端应用控制PLC>,作者: 云起MAE. 通过IoT云平台和边缘计算的技术设施,工厂可以将PLC等OT过程制造控制器 ...
- 从浅入深了解.NET Core MVC 2.x全面教程
一.基础 1.默认配置 使用Kestrel Web Server ASP.NET Core内置--跨平台 IIS集成 UseIIS() UseIISIntergration() Log IConfig ...
- [kubernetes]集群中部署CoreDNS服务
前言 从k8s 1.11版本开始,k8s集群的dns服务由CoreDNS提供.之前已经使用二进制文件部署了一个三master三node的k8s集群,现在需要在集群内部部署DNS服务. 环境信息 IP ...
- 一些不错的VSCode设置和插件
设置 同步设置 我们做的各项设置,不希望再到其他机器的时候还得再重新配置一次.VSCode中我们可以登陆微软账号或者GitHub账号,登陆后我们可以开启同步设置.开启设置同步,根据提示登陆即可. 允许 ...
- 记录一次解决数据库连接池连接泄露BUG
1 BUG现象 系统并发请求,系统停滞无法使用,所有接口都是无法与后端进行交互的状态,系统并没有宕机 2 BUG的业务流程 插入分数方法 涉及插入表ABCD 加了声明式事务 查询分数方法 涉及表ABC ...
- [HDCTF2019]Maze 反汇编-花指令处理
这是一道迷宫花指令加upx脱壳处理的题 先介绍花指令 一. 概述 花指令是对抗反汇编的有效手段之一,正常代码添加了花指令之后,可以破坏静态反汇编的过程,使反汇编的结果出现错误.错误的反汇编结果会造成破 ...
- datetime去除时分秒
datetime.datetime.now().replace(microsecond=0)
- HDFS核心概念与架构
HDFS简介 HDFS是Hadoop项目的核心子项目,在大数据开发中通过分布式计算对海量数据进行存储与管理,它基于流数据模式访问和处理超大文件的需求而开发,可以运行在廉价的商用服务器上,为海量数据提供 ...