今天刚学习了线段树,赶紧趁热打了两遍模版

下面都是线段树的基本操作,这个板子是维护的区间中的最大值,当然修改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)的更多相关文章

  1. HDU4614【线段树。】

    果然看了理解了一下大牛的代码然后自己敲结果果然有不少错误 回复说,线段树做为一种数据结构,最好以一种风格过一题裸的然后作为自己的模板.. 二分写的也很恶心哪 还有题目稍复杂一点的注定得推敲各种公式,不 ...

  2. HDU1394 Minimum Inversion Number(线段树OR归并排序)

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...

  3. Luogu3732 [HAOI2017] 供给侧改革 【后缀数组】【线段树】【乱搞】

    题目分析: 这道题我是乱搞的,因为他说$01$串是随机的. 那么我们可以猜测能够让LCP变大的地方很少.求出后缀数组之后可能让LCP变大的地方就等价于从大到小往height里动态加点同时维护这个点左右 ...

  4. BZOJ-2298|区间dp|线段树

    problem a Description 一次考试共有n个人参加,第i个人说:"有ai个人分数比我高,bi个人分数比我低."问最少有几个人没有说真话(可能有相同的分数) Inpu ...

  5. Luogu5289 十二省联考2019字符串问题(后缀数组+拓扑排序+线段树/主席树/KDTree)

    先考虑80分做法,即满足A串长度均不小于B串,容易发现每个B串对应的所有A串在后缀数组上都是一段连续区间,线段树优化连边然后判环求最长链即可.场上就写了这个. 100分也没有什么本质区别,没有A串长度 ...

  6. loj#2059. 「TJOI / HEOI2016」字符串 sam+线段树合并+倍增

    题意:给你一个子串,m次询问,每次给你abcd,问你子串sa-b的所有子串和子串sc-d的最长公共前缀是多长 题解:首先要求两个子串的最长公共前缀就是把反过来插入变成最长公共后缀,两个节点在paren ...

  7. hdu-1394(线段树&逆序数的性质和求法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题目大意: 给出一个序列,一对逆序数就是满足i<j&&a[i]>a[ ...

  8. 【BZOJ-4556】字符串 后缀数组+二分+主席树 / 后缀自动机+线段树合并+二分

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 657  Solved: 274[Su ...

  9. 字符串(tjoi2016,heoi2016,bzoj4556)(sam(后缀自动机)+线段树合并+倍增+二分答案)

    佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为\(n\)的字符串\(s\),和\(m\)个问题.佳媛姐姐必须正确回答这\(m\)个问题, ...

  10. 【题解】洛谷P1198 [JSOI2008] 最大数(线段树)

    洛谷P1198:https://www.luogu.org/problemnew/show/P1198 思路 一道水水的线段树 20分钟A掉 这道题只涉及到单点修改和区间查询 所以这道题甚至不用Laz ...

随机推荐

  1. Blazor资源大全,很棒的Blazor

    Blazor资源大全 一个收集了很棒的Blazor资源的集合. Blazor是一个使用C#/Razor和HTML在浏览器中运行的.NET Web框架. 欢迎贡献!请先查看贡献指南.感谢所有的贡献者,你 ...

  2. 带你掌握利用Terraform不同数据源扩展应用场景

    本文分享自华为云社区<利用Terraform不同数据源扩展应用场景>,作者: kaliarch . 一 背景 在生产环境中使用Terraform进行基础设施编排,通常又一些信息是通过其他外 ...

  3. SpringBoot整合Websocket,实现作为客户端接收消息的同时作为服务端向下游客户发送消息

    SpringBoot整合Websocket 1. SpringBoot作为服务端 作为服务端时,需要先导入websocket的依赖 <dependency> <groupId> ...

  4. Magick.NET跨平台压缩图片的用法

    //首先NuGet安装:Magick.NET.Core,Magick.NET-Q16-AnyCPUusing ImageMagick; /// <summary> /// 压缩图片 /// ...

  5. Centos安装 Apache Benchmark

    检查依赖包是否安装 1 rpm -qa|grep apr-util 2 3 rpm -qa|grep yum-utils 输出信息: 1 apr-util-1.5.2-6.el7.x86_64 2 y ...

  6. python中将时间转换为时间戳

    某平台url中的时间格式为时间戳,将时间变量传入url前,需要将固定格式的时间转换为时间戳.使用python中的time模块,对时间的几种格式进行转换. strptime(),将时间字符串转换成 结构 ...

  7. 给微软.Net runtime运行时提交的几个Issues

    前言 因为目前从事的CLR+JIT,所以会遇到一些非常底层的问题,比如涉及到微软的公共运行时和即时编译器或者AOT编译器的编译异常等情况,这里分享下自己提的几个Issues. Issues 一.iss ...

  8. 05 地址解析协议ARP

    地址解析协议(ARP) ARP(Address Resolution Protocol)地址解析协议: 根据已知的IP地址解析获得其对应的MAC地址 ARP工作流程 1.HOST1 ARP缓存 HOS ...

  9. github.com/yuin/gopher-lua 踩坑日记

    本文主要记录下在日常开发过程中, 使用 github.com/yuin/gopher-lua 过程中需要注意的地方. 后续遇到其他的需要注意的事项再补充. 1.加载LUA_PATH环境变量 在实际开发 ...

  10. api接口对接如何实现,php如何对接api

    API接口对接是现代软件开发中不可或缺的一部分,它允许不同的应用程序之间进行数据交换和服务调用.在PHP中,可以使用多种方式实现API接口的对接,包括基于HTTP协议的传统方法以及现代的API客户端库 ...