高级数据结构—线段树(一)

学线段树的原因是因为cf的一道题目始终想不出来怎么优化,后来知道区间查询和修改要用到线段树。。。

原题:Iva & Pav

线段树的作用

  1. 区间最值查询:可以高效地找到给定区间内的最大值、最小值等。

  2. 区间和查询:可以高效地计算给定区间内元素的和、积等。

  3. 区间更新:可以高效地对给定区间内的元素进行更新操作,如增加一个固定值、赋值等。

  4. 区间覆盖:可以将给定区间内的元素全部赋值为一个固定值。

  5. 区间合并:可以将多个区间合并成一个区间,快速地进行区间合并操作。

  6. 区间离散化:可以将区间内的元素进行离散化处理,方便进行查询和统计操作。

  7. 区间交集:可以快速地找到多个区间之间的交集

线段树和树状数组的区别 

 刚学完树状数组来学线段树,一开始还不知道他们具体的差别在哪里,那么以下是我的理解。

1.树状数组是前缀和优化,要用到前缀和的时候较为方便。

2.树状数组用来进行单点修改,区间查询;或者区间修改,单点查询较为方便,而区间查询和区间修改较为复杂,因此可以用线段树优化。

3.线段树适用于需要频繁的区间查询和更新操作的问题,如区间最值、区间和等,能够灵活处理各种区间操作。

4.树状数组适用于一维数组的前缀和查询和更新操作,对于简单的区间操作也能够提供高效的解决方案。

例题: 

最大数

题目链接:最大数

直接看代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
//单点插入,区间查询
const int N = 2e5+5;
struct node{int l,r;int v;
}tr[N*4];int m,p;//子节点的信息更新父节点
void pushup(int u){tr[u].v=max(tr[u<<1].v,tr[u<<1|1].v);
}//u为当前线段树节点编号
void build(int u,int l,int r){tr[u]={l,r};if(l==r)return;int mid=l+r>>1;build(u<<1,l,mid);build(u<<1|1,mid+1,r);
}//查询以u为根节点,区间[l,r]中的最大值
int query(int u, int l, int r) {//      Tl-----Tr//   L-------------R   //1.不必分治,直接返回if(tr[u].l >= l && tr[u].r <= r) return tr[u].v;int mid = tr[u].l + tr[u].r >> 1;int v = 0;//     Tl----m----Tr//        L-------------R //2.需要在tr的左区间[Tl, m]继续分治if(l <= mid) v = query(u << 1, l, r);//     Tl----m----Tr//   L---------R //3.需要在tr的右区间(m, Tr]继续分治if(r > mid) v = max(v, query(u << 1 | 1, l, r));//     Tl----m----Tr//        L-----R //2.3涵盖了这种情况return v;
}//u为节点编号,x为修改位置,v为修改的值
void modify(int u,int x,int v){if(tr[u].l==tr[u].r)tr[u].v=v;//叶子节点,递归出口else{int mid=tr[u].l+tr[u].r>>1;//分治,修改位置偏左往左边遍历,偏右往右边遍历if(x<=mid)modify(u<<1,x,v);else {modify(u<<1|1,x,v);}pushup(u);//回溯,子节点的信息更新父节点}
}signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);//n表示树中节点个数,last表示上一次查询的结果int n=0,last=0;cin>>m>>p;//初始化线段树,节点的区间最多为[1,m]build(1,1,m);while(m--){char op;cin>>op;if(op=='A'){//添加节点int t;cin>>t;//在n+1处插入modify(1,n+1,(t+last)%p);//节点个数+1n++;}else {int l;cin>>l;//查询[n - L + 1, n]内的最大值,u = 1,即从根节点开始查询last=query(1,n-l+1,n);cout<<last<<"\n";}}return 0;
}

你能回答这些问题吗

题目链接:你能回答这些问题吗

如图:

如图,假设我们要求区间的最大子段和,有三种情况:

1.包含所有左半边,部分右半边----->左半边的区间和+右半边的前缀和

2.包含所有右半边,部分左半边----->右半边的区间和+左半边的后缀和

3.中间的一部分----->左半边的后缀和+右半边的前缀和

因此我们的结构体要记录四个信息:

struct node{int l,r;int sum;//[l,r]的区间和int lmax;//最大前缀和int rmax;//最大后缀和int tmax;//区间[l,r]最大连续子段和
}tr[N*4];

 同时pushup函数根据上图可以推出:(重载函数)

//u表示该节点,l表示该节点的左子树,r表示该节点的右子树
void pushup(node &u,node &l,node &r){u.sum=l.sum+r.sum;//三种最大连续子段和的情况u.lmax=max(l.lmax,l.sum+r.lmax);u.rmax=max(r.rmax,r.sum+l.rmax);u.tmax=max({l.tmax,r.tmax,l.rmax+r.lmax});
}void pushup(int u){pushup(tr[u],tr[u<<1],tr[u<<1|1]);
}

代码附上:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5+5;
int w[N];
int n,m;
struct node{int l,r;int sum;//[l,r]的区间和int lmax;//最大前缀和int rmax;//最大后缀和int tmax;//区间[l,r]最大连续子段和
}tr[N*4];//u表示该节点,l表示该节点的左子树,r表示该节点的右子树
void pushup(node &u,node &l,node &r){u.sum=l.sum+r.sum;//三种最大连续子段和的情况u.lmax=max(l.lmax,l.sum+r.lmax);u.rmax=max(r.rmax,r.sum+l.rmax);u.tmax=max({l.tmax,r.tmax,l.rmax+r.lmax});
}void pushup(int u){pushup(tr[u],tr[u<<1],tr[u<<1|1]);
}void build(int u,int l,int r){if(l==r)tr[u]={l,r,w[r],w[r],w[r],w[r]};//找到叶子节点else{tr[u]={l,r};//设当前区间为[l,r]int mid=l+r>>1;build(u<<1,l,mid);//左子树build(u<<1|1,mid+1,r);//右子树pushup(u);//修改父节点}
}//每次从1号节点开始找,找到位置位于x的数,并把它修改为v
void modify(int u,int x,int v){if(tr[u].l==x && tr[u].r==x)tr[u]={x,x,v,v,v,v};else{int mid=tr[u].l+tr[u].r>>1;if(x<=mid)modify(u<<1,x,v);//x位于当前区间的左半子区间else modify(u<<1|1,x,v);//x位于当前区间的右半子区间pushup(u);//修改父节点的相关信息}
}node query(int u,int l,int r){if(tr[u].l>=l&&tr[u].r<=r)return tr[u];//被包含else{int mid=tr[u].l+tr[u].r>>1;if(r<=mid)return query(u<<1,l,r);//查询左半区间else if(l>mid)return query(u<<1|1,l,r);//查询右半区间else{//横跨左右区间auto left=query(u<<1,l,r);auto right=query(u<<1|1,l,r);node res;pushup(res,left,right);return res;}}
}signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n>>m;for(int i=1;i<=n;i++)cin>>w[i];build(1,1,n);//建树int k,x,y;while(m--){cin>>k>>x>>y;if(k==1){//查询if(x>y)swap(x,y);cout<<query(1,x,y).tmax<<"\n";}else modify(1,x,y);//修改}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/650483.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

俊杰测评:电视盒子什么牌子好?电视盒子品牌排行榜

欢迎各位来到俊杰的数码测评频道&#xff0c;每年我会进行数十次电视盒子测评&#xff0c;今年已经买过二十多款电视盒子了&#xff0c;本期的测评主题是电视盒子什么牌子好&#xff0c;通过十天的深入详细对比后我整理了电视盒子品牌排行榜&#xff0c;近期想买电视盒子的可以…

【软件】ERETCAD-Env:在轨空间环境3D动态仿真软件

文章介绍了Extreme-environment Radiation Effect Technology Computer-Aided Design – Environment (ERETCAD-Env)软件&#xff0c;文章的介绍和展示了ERETCAD-Env软件的功能和特点&#xff0c;这是一款用于动态模拟在轨卫星所处空间环境的计算机辅助设计软件。强调了该软件在…

for_earch

遍历容器执行函数 #include <iostream> #include <vector> #include <algorithm>void print_element(int x) {std::cout << "Element value: " << x << std::endl; }int main() {std::vector<int> vec { 1, 2, 3, 4, 5, …

贪心算法在找零问题中的应用

贪心算法在找零问题中的应用 引言a. 贪心算法求解找零问题算法设计算法证明 b. 硬币面额为c的幂时的贪心算法证明算法设计算法证明 c. 设计使贪心算法失效的硬币面额组合d. 通用找零算法设计算法设计算法实现&#xff08;伪代码&#xff09;算法实现&#xff08;C代码&#xff…

VS2019编译OSG3.7.0+OSGEarth3.3+OSGQt5.15.2时遇到的问题及解决方法

注:本次编译以文章《VS2019编译OSG3.7.0+OSGEarth3.3+OSGQt》为基础搜集资料并进行编译 一 OSG编译 1.Osg3.7.0编译中,cmake阶段按照文章步骤即可。 2.另外,还需要对以下三项进行设置,参照《OSG-OpenSceneGraph在WIN10与VS2022下的部署(OSG3.6.5+VS2022+Win10_x64)个…

Java后台开发的前置说明

1.知识点逻辑 一个部分 都是先挑重点知识点讲解 然后根据这些重点知识点去完成一个项目的开发 然后在到返回来解决这个部分其他细枝末节的知识点 2.软件开发的分工 我们大致可以将软件开发分成四块&#xff1a; 1.前端开发(比如开发电脑中的京东 htmlcssjavascript) 2.移动开…

构建高效的商品计划系统:为品牌增长注入新动力

在当今竞争激烈的市场环境中&#xff0c;商品计划对于品牌的成功至关重要。有效的商品计划系统不仅能够帮助企业精准地把握市场需求&#xff0c;优化生产流程&#xff0c;还能提升销售效率&#xff0c;改善客户体验&#xff0c;降低业务风险。本文将深入探讨有效的商品计划系统…

触发器的基本概念及分类

目录 触发器的基本概念 作用对象 触发事件 触发条件 触发时间 触发级别或者触发频率 触发器的分类 DML 触发器 INSTEAD OF 触发器 系统触发器 Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 触发器的基本概念 …

Recommended Azure Monitors

General This document describes the recommended Azure monitors which can be implemented in Azure cloud application subscriptions. SMT incident priority mapping The priority “Blocker” is mostly used by Developers to prioritize their tasks and its not a…

JAVA实现easyExcel动态生成excel

添加pom依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.6</version> </dependency><!--工具类--> <dependency><groupId>cn.hutool</groupId><…

丰富企业远控业务生态,向日葵开放多种远程控制API集成方案

随着远程控制技术不断应用在企业远程办公、IT运维、技术支持等场景中&#xff0c;他已经逐渐成为了企业软件工具中不可或缺的一种。随着企业远控需求的不断普及深入&#xff0c;市场也对远程控制解决方案最终实现的“形态”提出了更高的要求。 作为国民级远程控制品牌&#xf…

软件工程的介绍

软件工程 这一章的内容其实还是蛮多的,大概一共有10个章节,分别是下面的一些内容,但是呢,这一章的内容其实是比较偏向文科类的,也就是说,记忆的内容其实占有很大的篇幅,在该考试科目当中呢,其实也是主要影响上午题部分的选择题的考察,基本的分值呢,在10分左右,分值占…