(未经允许,严禁抄袭转载)(若有错误,请多多指教)
看了这张图后,大家可能明白建树的意思了
看代码以及注释
#include<bits/stdc++.h>
using namespace std;
void build(int ll,int rr,int num){
//表示当前为第num号区间[ll,rr]
e[num].l=ll,e[num].r=rr;
if(ll==rr){//即该区间只有一个叶节点
//e[num].maxx=a[ll];
//e[num].sum=a[ll];
return;//此处看题需要什么,连接表存
}
int mid=(ll+rr)>>1;
build(ll,mid,num*2);//左子树
build(mid+1,rr,num*2+1);//右子树
//e[num].maxx=max(e[num*2].maxx,e[num*2+1].maxx) 引题而异
}
//建树的实质为将一段长区间分成若干个小区间
//维护会很方便
int main(){
build(1,n,1);
return 0;
}
线段树建树到此就学完了
是不是非常清晰,明白
接下来是单点修改
很简单
代码注释能看懂就学会了
第一行是总结,可以最后看
//我们主要是来寻找这个点在哪,然后找到这个点所在区间长为1
//这样便于修改,我们只需要知道,每次的q在左子树还是右子树即可
#include<bits/stdc++.h>
using namespace std;
void update(int q,int x,int ll,int rr,num){
//将第q号节点增加(变为)x当前我们寻找到第num区间,左端点为ll,右端点为rr
if(ll==rr){//既找到该点所在的叶节点
a[num]+=x;//a[num]=x;
//e[num].maxx=a[num];
return;
}
int mid=(ll+rr)>>1;
if(q<=mid) update(q,x,ll,mid,num*2);
else update(q,x,mid+1,rr,num*2+1);
//可更新maxx,sum等等
//此处必须与建树对应
//如:q<=mid 因为该点在左子树上,mid为该区域端点
}
int main(){
update(q,x,1,n,1);
return 0;
}
个人认为已经解释清楚了
最后一个:区间查询
图片上的字会帮助你理解
#include<bits/stdc++.h>
using namespace std;
int query(int L,int R,int ll,int rr,int num){
//分别表示需要查询的区间[L,R],以及正在查询的区间编号为num,[ll,rr];
if(l>=L && r<=R)//正在查询的区间在需要查询区间内
return e[num].sum;
int mid=(l+r)>>1;
int ans=0;
if(L<=mid) ans+=query(L,R,l,m,num*2);
if(R>mid) ans+=query(L,R,mid+1,r,num*2+1);
//右子树与要查询区间有重叠
//此处可能两个都走
return ans;
}
int main(){
query(ll,rr,1,n,1)
return 0;
}
今天要讲的内容已经结束了
如果想要了解更多,可以学一下区间加值以及区间修改
如果有问题,请不吝赐教
祝大家一切顺利
再见!!!