浅谈线段树

-————终于从数论中爬出来了,没有继续写数论了
点修改
例题:给出一个有n个元素的数组a1,a2,a3,….an,设计一个数据结构,来支持修改某个元素和计算某个区间的最值
分析:因为要修改元素并且要计算最值,就不能再用ST表和遍历整个区间来计算,这两种方法的时间复杂度都较高,且如果一边修改元素,一边找最值,写出的代码就可以直接拿去卡死评测机.
所以我们要引入线段树(又名区间树)这个新的数据结构,而上述的两种问题的解决恰恰是线段树最优美的地方.
这里写图片描述
如图所示将n个元素由各个结点来储存,如在[5,7]中就可以储存5,6,7之中的最值.而如果要把7这个结点的值修改,则需要把结点[5,7],[1,7],[1,13]这三个结点的值修改.相比起将数组全部遍历,这种方法简单而高效啊.

#include<cstdio>
using namespace std;
int n;  int a[100100];  int minv[101000];
int minx(int xxx,int yyy){
    if(xxx<yyy)  return xxx;
    else  return yyy;
}
void init(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
       scanf("%d",&a[i]);
    }
}
void hebin(int k){
    minv[k]=minx(minv[k<<1],minv[k<<1|1]);
}
void jianshu(int ql,int qr,int o){
    if(ql==qr){
        minv[o]=a[ql];
        return;
    }
    int m=ql+(qr-ql)/2;
    jianshu(ql,m,o<<1);
    jianshu(m+1,qr,o<<1|1);
    hebin(o);
}
int main(){
    init();
    jianshu(1,8,1);
    return 0;
}

这是建树的代码,个人比较喜欢用递归实现(像不像快速排序)
下面是先是查询的代码,然后是更新的代码

int ql,qr; //全局变量(查询ql,q2中的最值),这里展示的是最小值 
int lookup(int o,int l,int r){  //o表示当前结点编号 
    int m=l+(r-l)/2,ans=INF;    //m这样写是一个小技巧,防止超int(尽量养成这个好习惯) 
    if(ql<=l && r<=qr)  return minv[o];
    if(ql<=m)  ans=minx(ans,lookup(o*2,ql,m));
    if(m<qr)  ans=minx(ans,lookup(o*2+1,m+1,qr));
    return ans;
}

int p,v;//将a[p]修改为v
void update(int o,int ql,int qr)
{
int m=ql+(qr-ql)/2;
if(ql==qr) minv[o]=v;
else
{
if(p<=m) update(o*2,ql,m);
else update(o*2+1,m+1,qr);
minv[o]=minx(minv[o*2],minv[o*2+1]);
}
}


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值