学习笔记 - 线段树
闲话(可忽略)
蒟蒻学业不精,到现在(现初二,并已考完期末考,看那狗屎whk和烂的一批的编程,不出意料过段时日就得退役)才勉强学到线段树,各位请引以为鉴。
正文(少到可怜)
好了,扯回正题,内容不多,就先呈上一份代码
/*
线段树简介:
线段树是算法竞赛中常用的用来维护 区间信息 的数据结构。
线段树可以在 O(log N) 的时间复杂度内实现单点修改、区间修改、区间查询(区间求和,求区间最大值,求区间最小值)等操作。
摘自 https://oi-wiki.org/ds/seg/
*/
// 线段树(区间修改,区间求和) 朴素
#include<stdio.h>
const int N=5e5;
int n,m,
a[N],sum[N],tag[N],d[N];
//
// 以下内容中 v,l,r 均表示为 下标为 v 的节点管辖区间 [l,r]
void build(int v,int l,int r)//建立线段树
{
if(l==r&&(sum[v]=a[l],1)) return ;//仅管辖一个
int mid=l+r>>1;
build(v<<1,l,mid),build(v<<1|1,mid+1,r);
sum[v]=sum[v<<1]+sum[v<<1|1];
}
void build(){build(1,1,n);}//方便使用
void maketag(int v,int l,int r,int k){sum[v]+=(r-l+1)*k,tag[v]+=k;}//制作 +k 的懒惰标记
void downtag(int v,int l,int r)//下放懒惰标记
{
if(!tag[v]) return;//如果没有标记,直接结束
int mid=l+r>>1;
maketag(v<<1,l,mid,tag[v]),maketag(v<<1|1,mid+1,r,tag[v]);//将标记给[l,mid]和[mid+1,r]的区间
tag[v]=0;//抹除当前标记
}
void upd(int v,int l,int r,int x,int y,int k)//将[x,y]范围内的+k
{
if(x<=l&&y>=r)//[l,r]的所有均在[x,y]范围内,直接加便可
{
maketag(v,l,r,k);
return;
}
if(tag[v]) downtag(v,l,r);//如果此时有标记,先下放
int mid=l+r>>1;
if(x<=mid) upd(v<<1,l,mid,x,y,k);//如果所更改范围[x,y]内容在该范围[l,mid]内,进行更新
if(y>mid) upd(v<<1|1,mid+1,r,x,y,k);//同上
sum[v]=sum[v<<1]+sum[v<<1|1];//进行更新
}
void upd(int x,int y,int k){upd(1,1,n,x,y,k);}//方便使用
int query(int v,int l,int r,int x,int y)//查询[x,y]范围数据之和
{
if(x>r||y<l) return 0;//走错位了,不是这区间,返回0
if(x<=l&&y>=r) return sum[v];//[l,r]的所有均在[x,y]范围内,直接加便可
int mid=l+r>>1;
if(tag[v]) downtag(v,l,r);//若有标记,下放
return query(v<<1,l,mid,x,y)+query(v<<1|1,mid+1,r,x,y);//返回自身两边区间相加之和
}
int query(int x,int y){return query(1,1,n,x,y);}//方便使用
//日常调用
//build(1,1,n) 对a建树
//update(x,y,k) 对建过树的 范围[x,y] 进行 +k 处理
//query(x,y) 对建过树的查询 [x,y]范围之和
//实践
int main()
{
int opt,x,y,k;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
build();
while(m--)
{
scanf("%d%d%d",&opt,&x,&y);
if(opt==1) scanf("%d",&k),upd(x,y,k);
else printf("%d\n",query(x,y));
}
return 0;
}
其实打完才想起可以发博客,内容可以写得更到位些,但都打完了,便算了,若以后有心,便再正经打份笔记
(但想来不太可能,以我的懒惰,连这代码版都拖了半个学期)
建议和线段树基础 - OI Wiki一起食用
闲话*2
emm....我回顾这个学期,前半个学期一如既往摸鱼划水,
临近期中考时,突然跟我讲之前考的CSP提高组2=可以参加提前招?摸了半个学期鱼的我(虽然我妈之前给我讲过)表示考不上的
经历了一个多星期的高强度学习(连期中考都没考)后,也是成功的没考上,但走了一位好友,哭哇
后面又是各种编程考试啊(回头又去复习编程的初赛基础),又是另一个提前招,两边忙得晕头转向,又都没做好,唉———
估计期末考也砸了,编程进度比期中那会还差点(当时好像把树状数组学了,这种基础线段树也比较熟练了,结果现在忘得差不多要回来整理了,有时间我还得把树状数组再看看)
最后,希望大家认真学习,莫要颓废,哦,对了,蒟蒻如果哪里有错不严谨,欢迎勘误
upd 2025.6.29 发现有个地方忘记写链接了,补上。哦对了,期末成绩竟然稳住了校排名一百多的名次(可还是比小升初那会差)唉,开心
upd 2025.7.9 修改代码错误
本人实力不济,若有错误,欢迎指出

浙公网安备 33010602011771号