备战蓝桥杯---线段树基础1

引入:RMQ问题:

什么是RMQ?

显然,我们无法用前缀维护,因此,我们需要用到线段树的知识:

什么是线段树?

线段树是用一种树状结构存储一个连续区间信息的数据结构

下面我们用图解释用它来查询2--5信息的方式:

由此,我们可以得到几点性质:

1.他是一个平衡的二叉树。

2.对于任意两个节点,要么完全包含,要么互不相交。

3.任意的线段[a,b]在查询过程中最多分为log(b-a)个。

4.除建树外为logn.

我们来一道模板题试试水:

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
int n,a[100000];
int tree[4*100000];
void build(int p,int l,int r){if(l==r){tree[p]=a[l];return;}int mid=(l+r)/2;build(p*2,l,mid);build(p*2+1,mid+1,r);tree[p]=tree[p*2+1]+tree[p*2];return;
}
void change(int p,int l,int r,int pos,int num){if(l==r){tree[p]+=num;return;}int mid=(l+r)/2;if(pos<=mid) change(p*2,l,mid,pos,num);else change(p*2+1,mid+1,r,pos,num);tree[p]=tree[2*p]+tree[2*p+1];return;
}
int calc(int p,int l,int r,int x,int y){if(l>=x&&r<=y){return tree[p];}int mid=(l+r)/2;if(y<=mid) return calc(p*2,l,mid,x,y);if(x>mid) return calc(p*2+1,mid+1,r,x,y);return calc(p*2,l,mid,x,mid)+calc(p*2+1,mid+1,r,mid+1,y);
}
int main(){cin>>n;for(int i=1;i<=n;i++) cin>>a[i];build(1,1,n);for(int i=1;i<=n;i++){int x,y,z;cin>>x>>y>>z;if(x==1){change(1,1,n,y,z);}else cout<<calc(1,1,n,y,z);} 
} 

让我们来看看它的实际应用吧:

区间和问题之懒标记:

我们维护一下节点的两个信息:

1.sum[i]第i个节点对应的区间和。

2.add[i]第i个节点对应区间整体加上的值并且没有同步给儿子。

这里我们就知道了为什么叫lazy,该标记仅当被标记的区间有部分被更改才顺路把标记下放给它的儿子。这样就可以减少修改的次数了。

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,a[100010],m;
int tree[4*100010];
int lazy[4*100010];
void build(int p,int l,int r){//建树 if(l==r){tree[p]=a[l];return;}int mid=(l+r)/2;build(p*2,l,mid);build(p*2+1,mid+1,r);tree[p]=tree[p*2+1]+tree[p*2];return;
}
void pushdown(int p,int l,int r){//lazy标记下移 int mid=(l+r)/2;lazy[p*2]+=lazy[p];lazy[p*2+1]+=lazy[p];tree[p*2]+=lazy[p]*(mid-l+1);//更新子节点的值 tree[p*2+1]+=lazy[p]*(r-mid);lazy[p]=0;//自己因为下移清0 
}
void change(int p,int l,int r,int x,int y,int num){if(x<=l&&r<=y){tree[p]+=num*(r-l+1);lazy[p]+=num;return;}if(lazy[p]!=0){//区间部分修改,需要下移 pushdown(p,l,r);}int mid=(l+r)/2;if(y<=mid) change(p*2,l,mid,x,y,num);if(x>mid) change(p*2+1,mid+1,r,x,y,num);if(x<=mid&&y>mid){change(p*2,l,mid,x,mid,num);change(p*2+1,mid+1,r,mid+1,y,num);}tree[p]=tree[2*p]+tree[2*p+1];return;
}
int calc(int p,int l,int r,int x,int y){if(l>=x&&r<=y){return tree[p];}if(lazy[p]!=0){pushdown(p,l,r);}int mid=(l+r)/2;if(y<=mid) return calc(p*2,l,mid,x,y);if(x>mid) return calc(p*2+1,mid+1,r,x,y);return calc(p*2,l,mid,x,mid)+calc(p*2+1,mid+1,r,mid+1,y);
}
signed main(){cin>>n>>m;for(int i=1;i<=n;i++) scanf("%lld",&a[i]);build(1,1,n);for(int i=1;i<=m;i++){int x,y,k,op;scanf("%lld%lld%lld",&op,&x,&y);if(op==1){scanf("%lld",&k);change(1,1,n,x,y,k);}else cout<<calc(1,1,n,x,y)<<endl;} 
} 

区间平方和问题:

我们还是用lazy标记,不过这时我们维护的sum应该是平方和。那么我们如何维护呢?

\sum (ai+k)^2=\sum ai^2+2k\sum ai+\sum k^2

因此我们只要维护ai的前缀和即可。

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,a[100010],m,sum[4*100010];
int tree[4*100010];
int lazy[4*100010];
void pushdown(int p,int l,int r);
int calc(int p,int l,int r,int x,int y,int k);
void build(int p,int l,int r){//建树 if(l==r){tree[p]=a[l]*a[l];sum[p]=a[l];return;}int mid=(l+r)/2;build(p*2,l,mid);build(p*2+1,mid+1,r);tree[p]=tree[p*2+1]+tree[p*2];sum[p]=sum[p*2+1]+sum[p*2+1];return;
}
void pushdown(int p,int l,int r){//lazy标记下移 int mid=(l+r)/2;lazy[p*2]+=lazy[p];lazy[p*2+1]+=lazy[p];tree[p*2]+=2*lazy[p]*(sum[2*p])+lazy[p]*lazy[p]*(mid-l+1);//更新子节点的值 tree[p*2+1]+=2*lazy[p]*(sum[2*p+1])+lazy[p]*lazy[p]*(r-mid);sum[p*2]+=lazy[p]*(mid-l+1);sum[p*2+1]+=lazy[p]*(r-mid);lazy[p]=0;//自己因为下移清0 
}
void change(int p,int l,int r,int x,int y,int num){if(x<=l&&r<=y){tree[p]+=2*num*(sum[p])+num*num*(r-l+1);sum[p]+=num*(r-l+1);lazy[p]+=num;return;}if(lazy[p]!=0){//区间部分修改,需要下移 pushdown(p,l,r);}int mid=(l+r)/2;if(y<=mid) change(p*2,l,mid,x,y,num);if(x>mid) change(p*2+1,mid+1,r,x,y,num);if(x<=mid&&y>mid){change(p*2,l,mid,x,mid,num);change(p*2+1,mid+1,r,mid+1,y,num);}tree[p]=tree[2*p]+tree[2*p+1];sum[p]=sum[2*p]+sum[2*p+1];return;
}
int calc(int p,int l,int r,int x,int y,int k){if(l>=x&&r<=y){if(k==1) return tree[p];else return sum[p];}if(lazy[p]!=0){pushdown(p,l,r);}int mid=(l+r)/2;if(y<=mid) return calc(p*2,l,mid,x,y,k);if(x>mid) return calc(p*2+1,mid+1,r,x,y,k);return calc(p*2,l,mid,x,mid,k)+calc(p*2+1,mid+1,r,mid+1,y,k);
}
signed main(){cin>>n>>m;for(int i=1;i<=n;i++) scanf("%lld",&a[i]);build(1,1,n);for(int i=1;i<=m;i++){int x,y,k,op;scanf("%lld%lld%lld",&op,&x,&y);if(op==1){scanf("%lld",&k);change(1,1,n,x,y,k);}else cout<<calc(1,1,n,x,y,1)<<endl;} 
} 

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

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

相关文章

【数据结构】队列OJ题《用队列实现栈》(题库+解析+代码)

1.前言 通过前面队列的实现和详解大家对队列应该有一定熟悉了&#xff0c;现在上强度开始做题吧 队列详解&#xff1a;http://t.csdnimg.cn/dvTsW 2.OJ题目训练225. 用队列实现栈 题目分析 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0…

【GPU驱动开发】- AST简介

前言 不必害怕未知&#xff0c;无需恐惧犯错&#xff0c;做一个Creator&#xff01; AST&#xff0c;抽象语法树&#xff0c;是一种包含丰富语义信息的格式&#xff0c;其中包括类型、表达式树和符号等。 TranslationUnitDecl&#xff1a;该类表示一个输入源文件 ASTContext&…

Qt注册类对象单例与单类型区别

1.实现类型SingletonTypeExample #ifndef SINGLETONTYPEEXAMPLE_H #define SINGLETONTYPEEXAMPLE_H#include <QObject>class SingletonTypeExample : public QObject {Q_OBJECT public://只能显示构造类对象explicit SingletonTypeExample(QObject *parent nullptr);//…

【学习笔记】深度学习实战 | LeNet

简要声明 学习相关网址 [双语字幕]吴恩达深度学习deeplearning.aiPapers With CodeDatasets 深度学习网络基于PyTorch学习架构&#xff0c;代码测试可跑。本学习笔记单纯是为了能对学到的内容有更深入的理解&#xff0c;如果有错误的地方&#xff0c;恳请包容和指正。 参考文献…

KubeEdge 边缘计算

文章目录 1.KubeEdge2.KubeEdge 特点3.KubeEdge 组成4.KubeEdge 架构 KubeEdge # KubeEdgehttps://iothub.org.cn/docs/kubeedge/ https://iothub.org.cn/docs/kubeedge/kubeedge-summary/1.KubeEdge KubeEdge 是一个开源的系统&#xff0c;可将本机容器化应用编排和管理扩展…

蓝牙耳机和笔记本电脑配对连接上了,播放设备里没有显示蓝牙耳机这个设备,选不了输出设备

环境&#xff1a; WIN10 杂牌蓝牙耳机6s 问题描述&#xff1a; 蓝牙耳机和笔记本电脑配对连接上了&#xff0c;播放设备里没有显示蓝牙耳机这个设备&#xff0c;选不了输出设备 解决方案&#xff1a; 1.打开设备和打印机&#xff0c;找到这个设备 2.选中这个设备&#…

Linux下gcc编译常用命令详解

在Linux环境下&#xff0c;使用gcc编译器进行源代码的编译是程序员日常工作的一部分。本篇将介绍一些常用的gcc编译命令&#xff0c;帮助开发者更好地理解和使用这些命令。 1. 基本编译命令 gcc工作流程&#xff1a; 编译单个源文件 gcc source.c -o output这个命令将sour…

调试工具vue,react,redux

React Developer Tools Redux DevTools Vue devtools 使用浏览器官方组件扩展搜索安装

枚举和联合(共用体)

目录 枚举枚举类型的定义枚举的优点 联合&#xff08;共用体&#xff09;联合类型的定义联合的特点联合大小的计算 枚举 枚举顾名思义就是一一列举&#xff0c;把可能的取值一一列举 枚举类型的定义 enum Day &#xff0c; enum Sex &#xff0c;enum Color 都是枚举类型{}中…

曾桂华:车载座舱音频体验探究与思考| 演讲嘉宾公布

智能车载音频 I 分论坛将于3月27日同期举办&#xff01; 我们正站在一个前所未有的科技革新的交汇点上&#xff0c;重塑我们出行体验的变革正在悄然发生。当人工智能的磅礴力量与车载音频相交融&#xff0c;智慧、便捷与未来的探索之旅正式扬帆起航。 在驾驶的旅途中&#xff0…

通过css修改video标签的原生样式

通过css修改video标签的原生样式 描述实现结果 描述 修改video标签的原生样式 实现 在控制台中打开设置&#xff0c;勾选显示用户代理 shadow DOM&#xff0c;就可以审查video标签的内部样式了 箭头处标出来的就是shodow DOM的内容&#xff0c;这些内容正常不可见的&#x…

MySQL 用了哪种默认隔离级别,实现原理是什么?

MySQL 的默认隔离级别是 RR - 可重复读&#xff0c;可以通过命令来查看 MySQL 中的默认隔离级别。 RR - 可重复读是基于多版本并发控制&#xff08;Multi-Version Concurrency Control&#xff0c;MVCC &#xff09;实现的。MVCC&#xff0c;在读取数据时通过一种类似快照的方…

视觉三维重建colmap框架的现状与未来

注&#xff1a;该文章首发3D视觉工坊&#xff0c;链接如下3D视觉工坊 前言 众所周知&#xff0c;三维重建的发展已经进入了稳定期&#xff0c;尤其是离线方案的发展几乎处于停滞期&#xff0c;在各大论刊上也很少见到传统sfmmvs亮眼的文章。这也不难理解&#xff0c;传统的多视…

MYSQL 解释器小记

解释器的结果通常通过上述表格展示&#xff1a; 1. select_type 表示查询的类型 simple: 表示简单的选择查询&#xff0c;没有子查询或连接操作 primary:表示主查询&#xff0c;通常是最外层的查询 subquery :表示子查询&#xff0c;在主查询中嵌套的查询 derived: 表示派…

【王道数据结构】【chapter8排序】【P360t2】

试编写一个算法&#xff0c;使之能够在数组L[1……n]中找出第k小的元素&#xff08;即从小到大排序后处于第k个位置的元素&#xff09;&#xff08;可以直接采用排序&#xff0c;但下面的排序的代码只是为了方便核对是不是第k小的元素&#xff0c;k从0开始计算&#xff09; #in…

出海手游收入一路高歌,营销上如何成功?

出海手游收入一路高歌&#xff0c;营销上如何成功&#xff1f; 以RPG和SLG为代表的中重度游戏一直是国内厂商在海外市场的传统优势品类&#xff0c;因为它们具有较高的投资回报率&#xff0c;是国内厂商在国际市场上取得成功的“吸金”利器。 据伽马数据发布的《2023全球移动游…

SpringCloud搭建微服务之Consul服务配置

1. 概述 前面有介绍过Consul既可以用于服务注册和发现&#xff0c;也可以用于服务配置&#xff0c;本文主要介绍如何使用Consul实现微服务的配置中心&#xff0c;有需要了解如何安装Consul的小伙伴&#xff0c;请查阅SpringCloud搭建微服务之Consul服务注册与发现 &#xff0c…

steam怎么付款

信用卡支付 登录Steam账户&#xff0c;选择需要购买的游戏或其他物品&#xff0c;点击“加入购物车”。在购物车页面点击“去结账”按钮&#xff0c;进入付款页面。在付款页面选择信用卡付款方式&#xff0c;填写信用卡信息&#xff0c;输入验证码&#xff0c;点击确认付款。 …

Servlet 新手村引入-编写一个简单的servlet项目

Servlet 新手村引入-编写一个简单的servlet项目 文章目录 Servlet 新手村引入-编写一个简单的servlet项目一、编写一个 Hello world 项目1.创建项目2.引入依赖3.手动创建一些必要的目录/文件4.编写代码5.打包程序6.部署7.验证程序 二、更方便的处理方案&#xff08;插件引入&am…

autocrlf和safecrlf

git远程拉取及提交代码&#xff0c;windows和linux平台换行符转换问题&#xff0c;用以下两行命令进行配置&#xff1a; git config --global core.autocrlf false git config --global core.safecrlf true CRLF是windows平台下的换行符&#xff0c;LF是linux平台下的换行符。…