线段树讲解

线段树作为数据结构中可以说是最重要的一个,在2016day2T2中首次在noip中出现虽然正解不是线段树
这就必须要求我们掌握这一数据结构,况且noip也不是我们的终点。
线段树是一种二叉搜索树,和区间树相似,我们将一个区间划分成一些单位区间,每个单位区间又对应着一个叶子节点
线段树可以实现快速查找(logn)修改
线段树是一种平衡二叉树,节点数是n即区间的长度
我们直接看代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 1001;

int z[N],tree[N << 2];   //z[N]表示一开始输入的数
//这份代码时间复杂度低一些,但是tree的大小必须至少 = 4*N

#define lson l,m,rt<<1  //规定左子树是father << 1
#define rson m+1,r,rt<<1|1  // .............+1

void build(int l,int r,int t);
void update(int rt); 
int query(int l,int r,int rt,int nowl,int nowr);

int main(){
 cin>>n;
 for(int i = 1;i <= n;i++){
  cin>>z[i];
 }
 build(1,n,1);
 return 0;
}
//sum表示区间和
void build(int l,int r,int t){
 if(l == r){
  sum[rt] = z[l]  //到了叶子结点显然区间和等于这个数
  return;
 }
 int m = (l + r) >> 1;l//m是分界点,然后我们分别初始化它的左子树和右子树
 build(lson);
 build(rson);
 update(rt); // update是计算sum值的函数,因为题目不同update函数不同为了方便拿出来写
}

void update(int rt){
 sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
//询问
int guery(int l,int r,int rt,int nowl,int nowr){
 if(nowl <= 1 && nowr > r) return sum[rt];
 int m = (l + r) >> 1;
 int ans = 0;
 if(nowl <= m) ans += query(lson,nowl,nowr);
 if(m < nowr) ans += query(rson,nowl,nower);
 return ans;
}
//单点修改 把第i个位置改成v
void modify(int l,int r,int rt,int p,int v){
 if(l == r){
  sum[rt] = v;
  return; // z找到了这个数
 }
 int m = (l + r) >> 1;
 if(p <= m) modify(lson,p,v);
 else modify(rson,p,v);
 update(rt);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值