线~段~树

news/2024/10/4 18:26:37
点击查看代码
#include<bits/stdc++.h>
#define lson id<<1
#define rson id<<1|1
using namespace std;
const int N=1e6+12000;
struct node{int l,r,num;int ma,mi;
}tr[N<<2];
int a[N];
int n,m;
string str;
int ans=0;
int from,to;
void build(int id,int l,int r){tr[id].l=l;tr[id].r=r;if(l==r){tr[id].num=a[l];tr[id].ma=a[l];tr[id].mi=a[l];return;}int mid=(l+r)/2;build(lson,l,mid);build(rson,mid+1,r);tr[id].num=tr[lson].num+tr[rson].num;tr[id].ma=max(tr[lson].ma,tr[rson].ma);tr[id].mi=min(tr[lson].mi,tr[rson].mi);
} 
void update(int id,int x,int ad){if(tr[id].l==tr[id].r){tr[id].num+=ad;tr[id].ma+=ad;tr[id].mi+=ad;return;}int mid=(tr[id].l+tr[id].r)/2;if(x<=mid) update(lson,x,ad);else update(rson,x,ad);tr[id].num=tr[lson].num+tr[rson].num; tr[id].ma=max(tr[lson].ma,tr[rson].ma);tr[id].mi=min(tr[lson].mi,tr[rson].mi);
}
int getsum(int id,int l,int r){if(r>=tr[id].r&&l<=tr[id].l){return tr[id].num;}int mid=(tr[id].l+tr[id].r)/2;if(mid<l) return getsum(rson,l,r);else if(mid>=r) return getsum(lson,l,r);else return getsum(lson,l,mid)+getsum(rson,mid+1,r);
}
int getmax(int id,int l,int r){if(r>=tr[id].r&&l<=tr[id].l){return tr[id].ma;}int maxn=0;int mid=(tr[id].r+tr[id].l)/2;if(mid<l) maxn=max(maxn,getmax(rson,l,r));else if(mid>=r) maxn=max(maxn,getmax(lson,l,r));else maxn=max({maxn,getmax(lson,l,mid),getmax(rson,mid+1,r)});return maxn;
}
int getmin(int id,int l,int r){if(r>=tr[id].r&&l<=tr[id].l){return tr[id].ma;}int minn=0x7fffffff;int mid=(tr[id].l+tr[id].r)/2;if(mid<l) minn=min(minn,getmin(rson,l,r));else if(mid>=r) minn=min(minn,getmin(lson,l,r));else minn=min({minn,getmin(lson,l,mid),getmin(rson,mid+1,r)});return minn;
}
int main(){cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}cin>>m;if(n) build(1,1,n);for(int i=1;i<=m;i++){cin>>str>>from>>to;if(str=="ADD"){update(1,from,to);}else{cout<<getsum(1,from,to)<<endl;}}
}

几个注意点
1.更新和建树跑到叶子时要return

if(tr[id].l==tr[id].r){tr[id].num+=ad;tr[id].ma+=ad;tr[id].mi+=ad;return;}
if(l==r){tr[id].num=a[l];tr[id].ma=a[l];tr[id].mi=a[l];return;}

2.关于取等

if(mid<l) return getsum(rs,l,r);else if(mid>=r) return getsum(ls,l,r);else return getsum(ls,l,mid)+getsum(rs,mid+1,r);

image
分别对应以上三行代码,因为我们是将l到mid定为lson,mid+1到r定为rson,所以查询的左边界要大于mid才能完全在右区间,而右边界仅需小于等于
3.区间处理(lazy标记)

点击查看代码
#include<bits/stdc++.h>
#define lson id<<1
#define rson id<<1|1
using namespace std;
const int N=1e6+1200;
int a[N];
int n,m;
struct node{int l,r,lazy,num;
}tr[N<<2];
void build(int id,int l,int r){tr[id].l=l;tr[id].r=r;if(l==r){tr[id].num=a[l];return;}int mid=(l+r)/2;build(lson,l,mid);build(rson,mid+1,r);tr[id].num=tr[lson].num+tr[rson].num;
}
void pushup(int id){tr[lson].lazy+=tr[id].lazy;tr[rson].lazy+=tr[id].lazy;tr[lson].num+=(tr[lson].r-tr[lson].l+1)*tr[id].lazy;tr[rson].num+=(tr[rson].r-tr[rson].l+1)*tr[id].lazy;tr[id].lazy=0;
}
void update(int id,int l,int r,int ad){if(l>tr[id].r||r<tr[id].l){return;}if(tr[id].r<=r&&tr[id].l>=l){tr[id].num+=ad*(tr[id].r-tr[id].l+1);tr[id].lazy+=ad;return;}int mid=(tr[id].l+tr[id].r)/2;pushup(id);update(lson,l,r,ad);update(rson,l,r,ad);tr[id].num=tr[lson].num+tr[rson].num;
}
int getsum(int id,int l,int r){if(l>tr[id].r||r<tr[id].l){return 0;}if(tr[id].r<=r&&tr[id].l>=l){return tr[id].num;}int mid=(tr[id].l+tr[id].r)/2;pushup(id);return getsum(lson,l,mid)+getsum(rson,mid+1,r);
}
int main(){string str;int from,to,w;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}build(1,1,n);cin>>m;for(int i=1;i<=m;i++){cin>>str;if(str=="SUM"){cin>>from>>to;cout<<getsum(1,from,to)<<endl;}else {cin>>from>>to>>w;update(1,from,to,w);}}
}
我们的目的是,将区间内所有的线段树都加上对应的值,但问题是,他太多了,所以我们要将添加的要求暂时放一下,所以就有了lazy标记
void pushup(int id){tr[lson].lazy+=tr[id].lazy;tr[rson].lazy+=tr[id].lazy;//处理id以及它的子树对应的总和,将子树以及它的子子树的处理先放置一边tr[lson].num+=(tr[lson].r-tr[lson].l+1)*tr[id].lazy;tr[rson].num+=(tr[rson].r-tr[rson].l+1)*tr[id].lazy;tr[id].lazy=0;//处理完清零
}

image
(画的不是太好,但基本是这么个意思)

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

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

相关文章

2024 年 5 月 7 日 周二 晴 常(324 字)

正文早上两头跑应付工作时,客户部的同事说我像被吸干了阳气。没办法啊,觉没睡够不就应该这样吗…… 休息好了肯定不这样。另外,才知道这周六补班,那一瞬间有些想死(笑。文竹的末端叶子好像还是没有变绿呢。有些担心。或许应该有点耐心?鱼儿的手机似乎坏了,于是也买了一个…

一种光电容积波PPG 转换到心电图ECG进行房颤检测的神经网络模型

具体的软硬件实现点击 http://mcu-ai.com/ MCU-AI技术网页_MCU-AI人工智能 光电体积描记法(PPG)是一种经济有效的非侵入性技术,利用光学方法测量心脏生理学。 PPG 在健康监测领域越来越受欢迎,并用于各种商业和临床可穿戴设备。与心电图(ECG)相比,PPG 并没有提供实质性的…

使用Selenium做网站登录的免验证

我发现,我已经三年多没有更新博客了。这几年一直感觉没什么可写的,工作上没遇到的问题python的不多,主要是前端页面上遇到的问题,感觉写起来比较困难,一写就要贴上去很多代码,还没什么必要,不贴又说不明白,所以干脆不写了。今年换了工作,开始研究新玩意儿了——爬虫。…

线程基本概念

1.进程与线程 1.1 进程进程是资源分配的单位,系统在运行时会为每个进程分配不同的内存区域 1.2 线程线程是调度和执行的单位,每个线程拥有独立的运行栈和程序计数器(pc),线程切换的开销小。一个Java应用程序java.exe,其实至少有三个线程:main()主线程(受异常影响),gc()…

在Gitlab Runner中调用Web Api写入Directory.Build.props需要的版本号文件

摘要 本文介绍了在Windows上的Gitlab Runner,如何调用web api更新版本号定义文件。 PowerShell function Update-Version {param ([string]$WEB_API_URL,[string]$NAMESPACE,[string]$VERSION_ID)echo "能生成或写入.props文件的web api的网站地址:"$WEB_API_URL …

.Net Core中使用RabbitMQ

开发中经常用到发布订阅的功能,之前一直用的Redis,使用过程中也出现了一些问题,后来换了RabbitMQ,用上去更顺手,简单记录一下。 正文开始: RabbitMQ是一个开源的,基于AMQP(Advanced Message Queuing Protocol)协议的完整的可复用的企业级消息队,RabbitMQ可以实现点对点,发…

一行SQL语句实现统计未来7天、按月统计数据,无数据填充0

未来7天、按月统计数据,无数据填充0 help_topic1 背景由于业务需求,在项目的报表中心中需要未来7天、按月统计数据,且要求按天补全数据,补数据填为0。  附实测SQL语句,请大家指正。 2 举例 2.1未来7天,按天补全数据,无数据填充0 sql语句:select t1.lastDays as x, IF…