代码源 线段树模板

news2024/9/30 17:37:48

线段树1

 

思路:

我们需要维护的东西是序列的最小值和最小值个数

这道题没有修改操作,因此不考虑修改

然后考虑Pushup

最小值很简单,直接取min

最小值个数怎么维护呢?考虑这个区间需要维护的值如何从左右两个区间获得

如果左右两个子区间的最小值相同,那么就可以直接相加

否则,如果这个区间的最小值是左区间最小值,直接赋值左区间的

否则就是右区间的

学一学dls的代码风格,感觉很高级QwQ

Code:

#include <bits/stdc++.h>

#define int long long

using namespace std;

const int mxn=2e5+10;
const int mxe=2e5+10;

struct info{
	int minv,mincnt;
};

info operator+(const info &l,const info &r){
	info a;
	a.minv=min(l.minv,r.minv);
	if(l.minv==r.minv) a.mincnt=l.mincnt+r.mincnt;
	else if(l.minv<r.minv) a.mincnt=l.mincnt;
	else a.mincnt=r.mincnt;
	return a;
}

struct ty{
	info val;
}tree[mxe<<2];

int n,Q,x,d,l,r,op;
int a[mxn]; 

void pushup(int rt){
	tree[rt].val=tree[rt<<1].val+tree[rt<<1|1].val;
}
void build(int rt,int l,int r){
	if(l==r){
		tree[rt].val={a[l],1};
		return;
	}
	int mid=l+r>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
	pushup(rt);
}
info query(int rt,int l,int r,int x,int y){
	if(x<=l&&r<=y){
		return tree[rt].val;
	}
	int mid=l+r>>1;
	if(y<=mid) return query(rt<<1,l,mid,x,y);
	else if(x>mid) return query(rt<<1|1,mid+1,r,x,y);
	else{
		return query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y);
	}
}
void change(int rt,int l,int r,int x,int k){
	if(l==r){
		tree[rt].val={k,1};
		return;
	}
	int mid=l+r>>1;
	if(x<=mid) change(rt<<1,l,mid,x,k);
	else change(rt<<1|1,mid+1,r,x,k);
	pushup(rt);
}
void solve(){
	cin>>n>>Q;
	for(int i=1;i<=n;i++) cin>>a[i];
	build(1,1,n);
	while(Q--){
		cin>>op;
		if(op==1){
			cin>>x>>d;
			change(1,1,n,x,d);
		}else{
			cin>>l>>r;
			cout<<query(1,1,n,l,r).minv<<" "<<query(1,1,n,l,r).mincnt<<'\n';
		}
	}
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int __=1;//cin>>__;
	while(__--)solve();return 0;
}

线段树2

题意:

 

思路:

我们需要维护一个区间的最大子段和

两个子区间的最大子段和怎么得到一整个区间的最大子段和呢

分类讨论即可

这个子段可能完全出现在左区间,也可能完全出现在右区间,也可能是左区间的右部分+右区间的左部分

前两种情况直接赋值即可

对于第三种情况,其实就是左区间的右部分最大子段和+右区间的左部分的最大子段和 之和

因此我们需要维护这两个值

然后开始考虑怎么维护

对于左部分最大子段和,它可能是左区间的左部分最大子段和,也有可能是左区间一整个区间+右区间的左部分最大子段和

右部分最大子段和同理

最后来看dls的板子,它需要写构造函数,因为我们这次在build的时候没有把所有的值都初始化

Code:

#include <bits/stdc++.h>

#define int long long

using namespace std;

const int mxn=2e5+10;
const int mxe=2e5+10;

struct info{
	int mss,mpre,msuf,s;
	info(){}
	info(int a) :mss(a),mpre(a),msuf(a),s(a){}
};

info operator+(const info &l,const info &r){
	info a;
	a.s=l.s+r.s;
	a.mss=max(max(l.mss,r.mss),l.msuf+r.mpre);
	a.mpre=max(l.mpre,l.s+r.mpre);
	a.msuf=max(r.msuf,r.s+l.msuf);
	return a;
}

struct ty{
	info val;
}tree[mxe<<2];

int n,Q,x,d,l,r,op;
int a[mxn]; 

void pushup(int rt){
	tree[rt].val=tree[rt<<1].val+tree[rt<<1|1].val;
}
void build(int rt,int l,int r){
	if(l==r){
		tree[rt].val=info(a[l]);
		return;
	}
	int mid=l+r>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
	pushup(rt);
}
info query(int rt,int l,int r,int x,int y){
	if(x<=l&&r<=y){
		return tree[rt].val;
	}
	int mid=l+r>>1;
	if(y<=mid) return query(rt<<1,l,mid,x,y);
	else if(x>mid) return query(rt<<1|1,mid+1,r,x,y);
	else{
		return query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y);
	}
}
void change(int rt,int l,int r,int x,int k){
	if(l==r){
		tree[rt].val=info(k);
		return;
	}
	int mid=l+r>>1;
	if(x<=mid) change(rt<<1,l,mid,x,k);
	else change(rt<<1|1,mid+1,r,x,k);
	pushup(rt);
}
void solve(){
	cin>>n>>Q;
	for(int i=1;i<=n;i++) cin>>a[i];
	build(1,1,n);
	while(Q--){
		cin>>op;
		if(op==1){
			cin>>x>>d;
			change(1,1,n,x,d);
		}else{
			cin>>l>>r;
			cout<<query(1,1,n,l,r).mss<<'\n';
		}
	}
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int __=1;//cin>>__;
	while(__--)solve();return 0;
}

线段树打标记

题意:

思路:

我们需要维护的是最大值,这个很好维护,Pushup直接取max即可

问题是需要区间修改,区间加

这个加个add标记即可,在Pushdown的时候更新mx属性

这种打标记的最重要的是如何在Pushdown的时候观察区间修改操作如何影响需要维护的值 

在这里很简单,直接最大值mx使加上add即可

Code:

#include <bits/stdc++.h>

#define int long long

using namespace std;

const int mxn=2e5+10;
const int mxe=2e5+10;

struct Segtree{
	int mx,add;
}tree[mxe<<2];

int n,Q,x,d,l,r,op;
int a[mxn]; 

void settag(int rt,int t){
	tree[rt].add+=t;
	tree[rt].mx+=t;
}
void pushup(int rt){
	tree[rt].mx=max(tree[rt<<1].mx,tree[rt<<1|1].mx);
}
void pushdown(int rt){
	if(tree[rt].add){
		settag(rt<<1,tree[rt].add);
		settag(rt<<1|1,tree[rt].add);
		tree[rt].add=0;
	}
}
void build(int rt,int l,int r){
	if(l==r){
		tree[rt]={a[l],0};
		return;
	}
	int mid=l+r>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
	pushup(rt);
}
int query(int rt,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr){
		return tree[rt].mx;
	}
	pushdown(rt);
	int mid=l+r>>1;
	if(qr<=mid) return query(rt<<1,l,mid,ql,qr);
	else if(ql>mid) return query(rt<<1|1,mid+1,r,ql,qr);
	else{
		return max(query(rt<<1,l,mid,ql,qr),query(rt<<1|1,mid+1,r,ql,qr));
	}
}
void modify(int rt,int l,int r,int ql,int qr,int d){
	if(ql<=l&&r<=qr){
		settag(rt,d);
		return;
	}
	pushdown(rt);
	int mid=l+r>>1;
	if(qr<=mid) modify(rt<<1,l,mid,ql,qr,d);
	else if(ql>mid) modify(rt<<1|1,mid+1,r,ql,qr,d);
	else{
		modify(rt<<1,l,mid,ql,qr,d);
		modify(rt<<1|1,mid+1,r,ql,qr,d);
	}
	pushup(rt);
}
void solve(){
	cin>>n>>Q;
	for(int i=1;i<=n;i++) cin>>a[i];
	build(1,1,n);
	while(Q--){
		cin>>op;
		if(op==1){
			cin>>l>>r>>d;
			modify(1,1,n,l,r,d);
		}else{
			cin>>l>>r;
			cout<<query(1,1,n,l,r)<<'\n';
		}
	}
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int __=1;//cin>>__;
	while(__--)solve();return 0;
}

线段树打标记2

题意:

 Code:

#include <bits/stdc++.h>

#define int long long

using namespace std;

const int mxn=2e5+10;
const int mxe=2e5+10;
const int mod=1e9+7;

struct tag{
	int mul,add;
};

tag operator+(const tag &l,const tag &r){
	return {(l.mul*r.mul)%mod,(l.add*r.mul+r.add)%mod};
}
struct Segtree{
	tag t;
	int val;
	int sz;
}tree[mxe<<2];

int n,Q,x,d,l,r,op;
int a[mxn]; 

void settag(int rt,tag t){
	tree[rt].t=tree[rt].t+t;
	tree[rt].val=(tree[rt].val*t.mul+tree[rt].sz*t.add)%mod;
}
void pushup(int rt){
	tree[rt].val=(tree[rt<<1].val+tree[rt<<1|1].val)%mod;
}
void pushdown(int rt){
	if(tree[rt].t.mul!=1||tree[rt].t.add!=0){
		settag(rt<<1,tree[rt].t);
		settag(rt<<1|1,tree[rt].t);
		tree[rt].t={1,0};
	}
}
void build(int rt,int l,int r){
	tree[rt].t={1,0};
	tree[rt].sz=r-l+1;
	if(l==r){
		tree[rt].val=a[l];
		return;
	}
	int mid=l+r>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
	pushup(rt);
}
int query(int rt,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr){
		return tree[rt].val;
	}
	pushdown(rt);
	int mid=l+r>>1;
	if(qr<=mid) return query(rt<<1,l,mid,ql,qr);
	if(ql>mid) return query(rt<<1|1,mid+1,r,ql,qr);
	return (query(rt<<1,l,mid,ql,qr)+query(rt<<1|1,mid+1,r,ql,qr))%mod;
}
void modify(int rt,int l,int r,int ql,int qr,tag t){
	if(ql==l&&r==qr){
		settag(rt,t);
		return;
	}
	pushdown(rt);
	int mid=l+r>>1;
	if(qr<=mid) modify(rt<<1,l,mid,ql,qr,t);
	else if(ql>mid) modify(rt<<1|1,mid+1,r,ql,qr,t);
	else{
		modify(rt<<1,l,mid,ql,mid,t);
		modify(rt<<1|1,mid+1,r,mid+1,qr,t);
	}
	pushup(rt);
}
void solve(){
	cin>>n>>Q;
	for(int i=1;i<=n;i++) cin>>a[i];
	build(1,1,n);
	while(Q--){
		cin>>op;
		if(op==1){
			cin>>l>>r>>d;
			modify(1,1,n,l,r,(tag){1,d});
		}else if(op==2){
			cin>>l>>r>>d;
			modify(1,1,n,l,r,(tag){d,0});
		}else if(op==3){
			cin>>l>>r>>d;
			modify(1,1,n,l,r,(tag){0,d});
		}else{
			cin>>l>>r;
			cout<<query(1,1,n,l,r)<<'\n';
		}
	}
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int __=1;//cin>>__;
	while(__--)solve();return 0;
}

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

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

相关文章

四.流程控制语句

1、条件语句 Go 编程语言中 if 条件语句的语法如下&#xff1a; 1、基本形式 if 布尔表达式 { /* 在布尔表达式为 true 时执行 */ } If 在布尔表达式为 true 时&#xff0c;其后紧跟的语句块执行&#xff0c;如果false 则不执行。 package main import "fmt" fu…

Spring MVC是什么?详解它的组件、请求流程及注解

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 前言 本文将讲解Spring MVC是什么&#xff0c;它的优缺点与九大组件&#xff0c;以及它的请求流程与常用的注解。 目录 一、Spring MVC是什…

计算机网络 - http协议 与 https协议(2)

前言 本篇介绍了构造http请求的的五种方式&#xff0c;简单的使用postman构造http请求&#xff0c;进一步了解https, 学习https的加密过程&#xff0c;了解对称密钥与非对称密钥对于加密是如何进行的&#xff0c;如有错误&#xff0c;请在评论区指正&#xff0c;让我们一起交流…

【数据科学和可视化】反思十年数据科学和可视化工具的未来

数据科学在过去十年中呈爆炸式增长&#xff0c;改变了我们开展业务的方式&#xff0c;并让下一代年轻人为未来的工作做好准备。但是这种快速增长伴随着对数据科学工作的不断发展的理解&#xff0c;这导致我们在如何使用数据科学从我们的大量数据中获得可操作的见解方面存在很多…

vue3实现一个简单的数字滚动效果

一、实现数字按步长递增的效果 1.实现思路 将这个组件封装起来&#xff0c;需要外部引用的文件传递两个值&#xff1a;指定数值 num 和 滚动持续时长 duration。首先设置一个增量 step&#xff0c;让数字按照这个增量来进行递增。然后设置一个定时器 setInterval&#xff0c;…

Flink集群部署总结

集群部署方式 Flink有两种部署方式&#xff0c;Standalone和Flink on Yarn集群部署方式。 Flink集群架构 Flink分布式架构是常见的主从结构&#xff0c;由JobManager和TaskManager组成。JobManager是大脑&#xff0c;负责接收、协调、分发Task到各个TaskManager&#xff0c;也…

靶场搭建——搭建pikachu靶场

搭建pikachu靶场 搭建pikachu靶场1、win11本机搭建步骤2、虚拟机win2012搭建步骤 我所碰见的问题以及解决方式&#xff1a; 搭建pikachu靶场 这里我所运用到的材料有&#xff1a;首先我最终是在虚拟机中环境为win2012和主机都搭建完成。 &#xff08;一个即可&#xff09; Ph…

在各数据库中使用 MERGE 实现插入避重 SQL

MERGE实现插入避重操作 前言 MERGE是一种在数据库管理系统中用于合并&#xff08;插入、更新或删除&#xff09;数据的SQL语句。它允许根据指定的条件将数据从一个表合并到另一个表中&#xff0c;同时避免重复插入或更新数据。 MERGE语句通常由以下几个关键字和子句组成&…

Spring Boot 中的服务消费

Spring Boot 中的服务消费 在分布式系统中&#xff0c;服务消费是一个很常见的场景。通过服务消费&#xff0c;可以将一个系统中的服务作为另一个系统中的组件来使用。Spring Boot 提供了很多工具来简化服务消费的过程&#xff0c;本文将深入探讨 Spring Boot 中的服务消费是什…

Java——《面试题——maven篇》

全文章节 Java——《面试题——基础篇》 Java——《面试题——JVM篇》 Java——《面试题——多线程&并发篇》 Java——《面试题——Spring篇》 Java——《面试题——SpringBoot篇》 Java——《面试题——MySQL篇》​​​​​​ Java——《面试题——SpringCloud》 Java——…

Redis数据库的简介、部署及常用命令

Redis数据库的简介、部署及常用命令 一、关系数据库与非关系型数据库概述1、关系型数据库2、非关系型数据库3、关系数据库与非关系型数据库区别4、非关系型数据库产生背景 二、Redis简介1、Redis服务器程序的单线程模型2、Redis的优点 三、Redis部署四、Redis 命令工具1、redis…

全概率公式和贝叶斯公式

人工智能和机器学习中经常听到一个著名公式&#xff1a;贝叶斯概率公式。早已忘记了&#xff0c;赶紧记一下笔记。 &#xff08;一&#xff09;全概率公式&#xff1a; 注意&#xff1a;全概率公式成立的前提是Bi是样本的划分 其证明过程如下&#xff1a; &#xff08;二&…

C++笔记之互斥锁,原子变量,条件变量对比

C笔记之互斥锁&#xff0c;原子变量&#xff0c;条件变量对比 code review! 目的&#xff1a;避免多线程间共享数据的竞态条件。 文章目录 C笔记之互斥锁&#xff0c;原子变量&#xff0c;条件变量对比1.std::mutex——互斥锁2.std::lock_guard3.std::unique_lock4.std::ato…

C++之lambda函数应用(一百四十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

如何看懂时序图(1):时序图基础知识

对于参考手册中经常出现的一些时序图&#xff0c;经常会让我摸不着头脑。比如对于Flash的时序图来说&#xff0c;要看懂的话&#xff0c;里面的每一个参数都得系统地学一遍&#xff0c;而且时序图中的一些符号也不太懂是什么意思。前一段时间调HyperRAM的时候&#xff0c;因为那…

冯·诺依曼架构哈佛架构(嵌入式学习)

冯诺依曼架构&哈佛架构 0. 前言1. 冯诺依曼架构&#xff08;von Neumann architecture&#xff09;关键组件限制&挑战 2. 哈佛架构关键组件限制&挑战 3. 冯诺依曼架构&哈佛架构的区别4. 知识扩展 0. 前言 冯诺依曼架构&#xff08;von Neumann architecture&a…

Python 命令行参数

Python 命令行参数 1、sys 库 sys.argv 获取参数2、getopt 模块解析带-参数2.1 短参数shortopts2.1.1 无短参数2.1.2 短参数h无值2.1.3 短参数h有值2.1.4 多个短参数h:v 2.2 长参数longopts2.2.1 长参数无值2.2.2 长参数有值 2.3 有空格字符串值 1、sys 库 sys.argv 获取参数 s…

Kubernetes核心概念汇总—调度、抢占和驱逐(Pod 调度就绪态)

Pod 一旦创建就被认为准备好进行调度。 Kubernetes 调度程序尽职尽责地寻找节点来放置所有待处理的 Pod。 然而&#xff0c;在实际环境中&#xff0c;会有一些 Pod 可能会长时间处于"缺少必要资源"状态。 这些 Pod 实际上以一种不必要的方式扰乱了调度器&#xff08;…

Vue3 如何去开发安卓 或者 ios

Vue3 有没有一款好用的开发原生的工具 1.uniapp 我个人认为uniapp 适合开发小程序之类的&#xff0c;用这个去开发原生应用会存在一些问题 性能限制&#xff1a;由于 Uniapp 是通过中间层实现跨平台&#xff0c;应用在访问底层功能时可能存在性能损失。与原生开发相比&#xf…

【Linux】调试工具gdb

目录 前言 一、前情了解 二、gdb常用命令 1.基本指令 2.断点 3.调试过程 4.查看内容 前言 gdb是Linux环境下了一个调试工具&#xff0c;在代码运行出现问题时&#xff0c;我们可以通过它来进行调试&#xff0c;找出问题的所在。本文来带大家来了解一下gdb的使用方法。 …