线段树(待更新)

本文介绍了使用线段树数据结构来优化数组操作,特别是针对区间查询和单点修改的问题。通过建立线段树,可以在O(logN)的时间复杂度内完成这些操作,显著提高了效率。示例代码展示了如何构建、更新和查询线段树,适用于处理动态区间最大值问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一种降低时间复杂度的空间储存方法。

 对于一个数组  a[N](这里N=16)

可以采取线段树  tr[N]  的方式储存

方便进行   单点修改、区间查询。

样式图:(1—16:表示存一个在1~16这个区间内的属性)

1———————16
   1 —— 8        9——16
1——45——89——1213——16
1——23——45——67——89——1011——1213——1414——16
1234567810111213141516

接下来是一个完整版子

//  main.cpp
//  线段树
//区间最大值线段树
#include <iostream>
#include <cstring>
#include <math.h>
using namespace std;
#define N 10001
int tr[N*4];//为了从 总数/2 处开始建立
//线段树建立
void build(int rt,int l,int r)
{
    if(l==r)
    {scanf("%d",&tr[rt]);return;}
    int m=(l+r)/2;//取中间值
    build(2*rt,l,m);//建立左子节点
    build(2*rt+1,m+1,r);//建立右子节点
    tr[rt]=max(tr[rt*2],tr[rt*2+1]);//取两个字节点的最大值
}
//更改某一节点的值
void charge(int rt,int l,int r,int u,int num)
{
    if(r==l)
    {tr[rt]=num;return;}
    int m=(l+r)/2;
    if(u<=m)  charge(2*rt,l,m,u,num);//完善左节点
    else      charge(2*rt+1,m+1,r,u,num);//完善右节点
    tr[rt]=max(tr[rt*2],tr[rt*2+1]);//完善树
}
//查找区间最大值
int max_of_query(int rt,int l,int r,int L,int R)
{
    if(L==l && R==r)//判断整体在不在一个完整的区间里
        return tr[rt];//返回该区间的值
    int m=(r+l)/2;
    int maxl=0;//定义最大值
    if(L<=m)
    {
        if(R>m)//判断右端点是否在区间内
            maxl=max(maxl,max_of_query(rt*2,l,m,L,m));
        else
            maxl=max(maxl,max_of_query(rt*2,l,m,L,R));
    }//左子区间
    if(R>=m+1)
    {
        if(L<m+1)//同上
            maxl=max(maxl,max_of_query(rt*2+1,m+1,r,m+1,R));
        else
            maxl=max(maxl,max_of_query(rt*2+1,m+1,r,L,R));
    }//右子区间
    return maxl;
}
//生成树
void see_tree(int tr[])
{
    int i,j=1;
    for(i=1;tr[i]!=0;i++)
    {
        if(i==pow(2,j))
        {printf("\n");j++;}
        printf("%d\t",tr[i]);
    }
}
int main()
{
    int n;
    int u,num;
    int l,r,mx;
    cin>>n;
    
    build(1,1,n);//建立一个从1~n的最大值线段树
    see_tree(tr);
    
    cin>>u>>num;//改位置u上的数为num
    charge(1,1,n,u,num);
    see_tree(tr);
    
    cin>>l>>r;//查找区间(l,r)最大值
    mx=max_of_query(1,1,n,l,r);
    printf("%d",mx);
    //see_tree(tr);
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值