这个博主的线段树我觉得讲的很细了

建树

struct node{
   
	ll l,r;
	ll sum,mlz,plz;
}tree[4*maxn];
inline void bulid(int i,int l.int r)
{
   
	tree[i].l=1;
	tree[i].r=r;
	if(l==r){
   
		tree[i].sum=input[i];
		return ;
	}
	int min=(l+r)>>1;
	bulid(i*2,l,min);
	bulid(i*2+1,min+1,r);
	tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
}

区间查询,单点修改

inline int search(int i,int l,int r){
   
	if(tree[i].l>=l&&tree[i].r<=r)return tree[i].sum;
	if(tree[i].r<l||tree[i].l>r)return 0;
	int sum=0;
	if(tree[i*2].r>=l)sum+=search(i*2,l,r);
	if(tree[i*2+1].l<=r)sum+=search(i*2+1,l,r);
	return sum;
}
inline void add(int i,int dis,int k)
{
   
	if(tree[i].l==tree[i].r)
	{
   
		tree[i].sum+=k;
		return;
	}
	if(dis<=tree[i*2].r)add(i*2,dis,k);
	else add(i*2+1,dis,k);
	tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
	return ;
}

区间修改,单点查询

inline void add(int i,int l,int r,int k)
{
   
	if(tree[i].l>=l&&tree[i].r<=r){
   
		tree[i].num+=k;
		return;
	}
	if(tree[i*2].r>=l)add(i*2,l,r,k);
	if(tree[i*2+1].l<=r)add(i*2+1,l,r,k);
}
void search(int i,int dis){
   
	ans+=tree[i].num;
	if(dis<=tree[i*2].r)
        search(i*2,dis);
    if(dis>=tree[i*2+1].l)
        search(i*2+1,dis);
} 

区间修改,区间查询(带pushdown)

void push_down(int i)
{
   
	if(tree[i].lz)
	{
   
		tree[i*2].lz+=tree[i].lz;
		tree[i*2+1].lz+=tree[i].lz
		
		int mid=(tree[i].l+tree[i].r)/2;
		
		tree[i*2].sum+=tree[i].lz*(mid-tree[i*2].l+1);
		tree[i*2+1].sum+=tree[i].lz*(tree[i*2+1].r-mid);
		tree[i].lz=0;
	}
	return 0;
}
void add(int i,int l,int r,int k){
   
	if(tree[i].r<=r&&tree[i].l>=l)
	{
   
		tree[i].sum+=k*(tree[i].r-tree[i].l+1);
		tree[i].lz+=k;
		return;
	}
	push_back(i);
	if(tree[i*2].r>=l)add(i*2,l,r,k);
	if(tree[i*2+1].l<=r)add(i*2+1,l,r,k);
	tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
	return 0;
}
inline int search(int i,int l,int r){
   
	if(tree[i].l>=l&&tree[i].r<=r)return tree[i].sum;
	if(tree[i].r<l||tree[i].l>r)return 0;
	push_back(i);
	int sum=0;
	if(tree[i*2].r>=l)sum+=search(i*2,l,r);
	if(tree[i*2+1].l<=r)sum+=search(i*2+1,l,r);
	return sum;
}

乘法线段树

根号线段树