线段树(sgement tree)是一种分治思想的二叉树结构,用于在区间上进行信息统计。与按照二进制位进行区间划分的树状数组相比,线段树是一种更加通用的结构:
1.线段树的每个节点都代表一个区间。
2.线段树具有唯一的根节点,代表的区间是整个统计范围,如[1,n]。
3.线段树的每个叶节点都代表一个长度为1的元区间,如[x,x]
4.对于每个内部
线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩。
在这片文章中,我先讲一下最基本的建树,单点修改,单点/区间查询
线段树是一种用空间换时间的算法开建树的数组时切记 一定要开4倍的数组
#include
using namespace std;
const int maxn=10000+10;
int a[maxn],sum[maxn*4]; //四倍空间
inline int read(){ //快读,没啥特殊意思
int s=0,w=1;
char ch=getchar();
while(ch<='0' || ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0' && ch<='9'){s=s*10+ch-48;ch=getchar();}
return s*w;
}
inline void pushup(int root){ //这个节点的值是该节点的左节点加右节点的和
sum[root] = sum[root<<1]+sum[root<<1|1];
}//乘2是该节点的左节点,再加1则是右节点
inline void build(int l,int r,int root){//建树
if(l == r){
sum[root] = a[l];
return;
}
int mid = (l+r)>>1;
build(l,mid,root<<1);
build(mid+1,r,root<<1|1);
pushup(root);
}
inline void update(int l,int r,int root,int num,int w){//更新
if(l == r){
sum[root] += w;
return;
}
int mid = (l+r)>>1;
if(num <= mid)update(l,mid,root<<1,num,w);
if(num > mid)update(mid+1,r,root<<1|1,num,w);
pushup(root);
}
inline int query(int l,int r,int root,int num){//查询
if(l == r)return sum[root];
int mid = (l+r)>>1;
if(num <= mid)return query(l,mid,root<<1,num);
if(num > mid)return query(mid+1,r,root<<1|1,num);
}
inline int query2(int root,int l,int r,int L,int R){//区间查询
if(L <= l && r <= R)
return sum[root];
int mid = (l+r)>>1,tmp = 0;
if(L <= mid)
tmp += query2(root<<1,l,mid,L,R);
if(mid < R)
tmp += query2(root<<1|1,mid+1,r,L,R);
return tmp;
}
int main(){
int n;
n = read();
for(int i = 1;i <= n;i++)scanf("%d",&a[i]);
build(1,n,1);
// for(int i = 1;i <= n*2-1;i++)printf("%d%c",sum[i],i == n?'\n':' ');
for(int i = 1,op,x,y,L,R;i <= 10;i++){
scanf("%d",&op);
if(op == 1)scanf("%d%d",&x,&y),update(1,n,1,x,y);
if(op == 2)scanf("%d",&x),printf("%d\n",query(1,n,1,x));
if(op == 3)scanf("%d%d",&L,&R),printf("%d\n",query2(1,1,n,L,R));
}
return 0;
}
数组实现线段树建树,单点修改,区间/单点查询
如果单单只是区间查询就没必要pushdowm,用不着
结构体的就懒得打了
自己想去