线段树(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 ...
随机推荐
- Matlab2021a打包jar包问题(linux、windows)
都有chatgpt了,实在不想写博客....不过还是记录一下问题吧. 我们在用matlab打包jar包的时候,经常会出现打包出错的问题,但无非注意以下几点就行了: 1.打包方式 这个还是很简单的,而且 ...
- 工作笔记--简单网线连接,使另一台设备通过笔记本电脑的wifi上网
条件 笔记本电脑能够通过 wifi 上网 另一台与笔记本电脑网线连接正常 配置固定 ip,使之可以互相 ping 通 操作 点击右下角 wifi 图标,点击[网络和 Internet 设置] 在高级网 ...
- React: 路由重定向
解决方案 参考链接 https://v5.reactrouter.com/web/example/route-config
- 一种flink 作业提交失败的情况描述与原因排查
遇到异常 2019-12-24 16:49:59,019 INFO org.apache.flink.yarn.YarnClusterClient - Starting client actor sy ...
- ABC295 D题 题解
题意简述 给定一个长度不超过\(\;5\times 10^5\;\)的,仅有数字构成的字符串,问存在多少段子串,使得子串内字符重新排序后,前半段与后半段相同? 做法分析 重组后前后两部分相同,其实也就 ...
- 【Azure K8S | AKS】在不丢失文件/不影响POD运行的情况下增加PVC的大小
问题描述 在前两篇文章中,创建了Disk + PV + PVC + POD 方案后,并且进入POD中增加文件. [Azure K8S | AKS]在AKS集群中创建 PVC(PersistentVol ...
- 详细讲解原生js拖拽
场景描述 今天遇见一个问题,那就是产品希望在弹出来的窗口. 可以移动这个弹窗的位置 增加用户体验,我们直接使用的element-ui中的 Dialog 对话框 我们现在需要拖拽标题,移动元素位置 元素 ...
- Leetcode刷题笔记——单调性
单调性 单调性是数学中使用的一种常见性质,通常用于描述函数,在高等数学中的定义常常为: 设函数f(x)在区间I上有定义,如果对于I上的任意两个数x1和x2,当x1<x2时,有f(x1)<f ...
- iOS发送探针日志到日志系统的简单实现
通过参考Testin的SDK实现方式,我们大致可以确定他们背后的实现方式: 首先,通过加载Testin的SDK,然后收集各种七七八八的数据,再通过socket发送数据到云端. 云端我们已经有了,就是h ...
- springboot整合feign的接口抽离
前言 现在很多微服务框架使用feign来进行服务间的调用,需要在服务端和消费端两边分别对接口和请求返回实体进行编码,维护起来也比较麻烦.那有木有一种可能,只用服务端编写接口,客户端像本地方法一样调用, ...