线段树的简单操作(入门级别)

线段树的简单操做


一些线段数的基本操作
比如建树,单点修改,单点查询, 单点修改和区间查询(区间和), 区间修改和区间查询,甚至 单点询问,区间修改。这些操作都是有着差异性。尤其是区间修改,需要用到Llazy标记。
另外,建树也分为很多种(取决于每个父结点的意义)
比如以最大或最小值建树(有的题还让你求一个区间内最大与最小值之间的落差,这种情况只要开一个结构体即可),还有区间和。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 400010
int inf=99999999;
using namespace std;
long long mi[N],a[N];
long long p=1,q=1;

void buildmin(int k,int l,int r)     //最小值建树
{
    if(l==r)
    {
        mi[k]=a[l];
        return;
    }
    int mid=(l+r)/2;
    buildmin(k<<1,l,mid);
    buildmin(k<<1|1,mid+1,r);
    mi[k]=min(mi[k<<1],mi[k<<1|1]);//自下而上,当前K取左右儿子较小,**该位置的条件因题而异**
}

void buildsum(int k,int l,int r)     //求和建树
{
    if(l==r)
    {
        mi[k]=a[l];
        return;
    }
    int mid=(l+r)/2;
    buildsum(k<<1,l,mid);
    buildsum(k<<1|1,mid+1,r);
    mi[k]=mi[k<<1]+mi[k<<1|1];  //变化仅此而已
}

int query_min(int k,int l,int r,int x,int y) //简单的区间询问操作
{
    if(r<x||l>y)return inf;
    if(x<=l&&r<=y)return mi[k];
    int mid=(l+r)/2;
    return min(query_min(k<<1,l,mid,x,y),query_min(k<<1|1,mid+1,r,x,y));   //果然,最小值建树区间访问求最小值比较容易....
}

void change(int k,int l,int r,int x,int v)     //点修改操作
{
    if(l>x||r<x)return;
    if(l==r&&l==x)
    {
        mi[k]=v;
        return;
    }
    int mid=(l+r)/2;
    change(k<<1,l,mid,x,v);
    change(k<<1|1,mid+1,r,x,v);
    mi[k]=min(mi[k<<1],mi[k<<1|1]);  //感觉和建树bulid类似
}

int main()
{
    int i,j,n;
    scanf("%d",&n);
    for(i=1; i<=n; i++)
        scanf("%lld",&a[i]);


    //1.最小值建树检验
    buildmin(1,1,n);
    for(i=1; i<=n*2-1; i++)
        printf("%lld ",mi[i]);
    printf("\n");


    //2.把第X个数变成V,检验
    change(1,1,n,1,2);
    for(i=1; i<=n*2-1; i++)
        printf("%lld ",mi[i]);
    printf("\n");


    //3.最小值区间访问,访问区间:[t1,t2]
    int t1,t2,tt;
    scanf("%d%d",&t1,&t2);
    tt=query_min(1,1,n,t1,t2);
    printf("%d\n",tt);

    //4.和建树检验
    buildsum(1,1,n);
    for(i=1; i<=n*2-1; i++)
        printf("%lld ",mi[i]);
    printf("\n");
}
/*
测试数据:
8
5 3 7 9 6 4 1 2
3 4

3 4 表示查询区间[3,4]的最小值,应该为7

最小值建数注意:
1.最好build(1,1,n)
2.l=r时,mi[k]=a[l],这个时候的l正号对应相应序列的ID   
3.建树mi[4*n]
4.(n<<1)-1   括号不能少    (n<<1-1..算术优先)

*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值