线段树

用数组实现线段树 ,当前节点为 now,左儿子是now*2右儿子是now*2+1,父节点now/2.注意线段树的数组大小,用 最大子叶个数的4倍。

左儿子为父节点的前半个区间,右儿子 为父节点的后半个区间。




#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include<string>
#include <math.h>


#define MOD 1000000007;


using namespace std;


struct  node
{
    int v;
    int l;
    int r;
    node(int a, int b, int c)
    {
        v = a;
        l = b;
        r = c;
    }
    node()
    {
        v = 0;
        l = 0;
        r = 0;
    }
};


node ltree[4000005];
int z[1000005];
int son[1000005];


int creata(int now, int l, int r)
{
    ltree[now].l = l;
    ltree[now].r = r;

    if(l == r)
    {
        son[l] = now;
        ltree[now].v = z[l];
        return z[l];
    }

    int m = (l + r) >> 1;
    ltree[now].v = min(creata(now * 2, l, m), creata(now * 2 + 1, m + 1, r));
    return ltree[now].v;
}


int find(int now, int l, int r)
{
    if(ltree[now].l == l && ltree[now].r == r)
    {
        return ltree[now].v;
    }

    int m = (ltree[now].l + ltree[now].r >> 1);

    if(r <= m)
    {
        return find(now * 2, l, r);
    }
    else
        if(l > m)
        {
            return find(now * 2 + 1, l, r);
        }
        else
        {
            return min(find(now * 2, l, m), find(now * 2 + 1, m + 1, r));
        }
}


int main()
{
    int N, Q, x, y, y2;

    while(~scanf("%d", &N))
    {
        for(int i = 1; i <= N; ++i)
        {
            scanf("%d", &z[i]);
        }

        creata(1, 1, N);
        scanf("%d", &Q);

        for(int i = 0; i < Q; ++i)
        {
            scanf("%d %d %d", &x, &y, &y2);

            if(x)
            {
                int now = son[y];
                ltree[now].v = y2;

                while(now > 1)
                {
                    int fa = now / 2;
                    int _MIN = min(ltree[fa * 2].v, ltree[fa * 2 + 1].v);

                    if(ltree[fa].v == _MIN)
                    {
                        break;
                    }
                    else
                    {
                        ltree[fa].v = _MIN;
                        now = fa;
                    }
                }
            }
            else
            {
                printf("%d\n", find(1, y, y2));
            }
        }
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值