hdu1754 线段树(查找和单点更新)

本文介绍了一种数据结构——线段树,并通过一个具体题目详细解释了如何利用线段树来高效解决区间查询问题,包括线段树的构建、查询及更新操作。

        刚刚开始学线段树,看见中文题就很开心~

    线段树是一种二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。


   这题的查询要求是得到区间内成绩最好的那个。查区间,故用线段树。

首先,要建立一颗线段树,每个根结点的值是两个子结点里更大的那个。

然后,开始查,就是对比区间,有三种情况,老师给出的区间不在区间里,给出的区间完全被包含在区间里,给出的区间部分包含在区间里

第一种可以直接返回了,第二种直接输出该区间的最大值,第三种还得两边继续往下查

这是查找

还有更新,知道是哪个点,一直更~

//线段树的建立,维护最大值和单点更新

#include<stdio.h>

#define maxn 200010
#define maxm 5010

struct node{
    int left,right,max;
}tree[maxn<<2];

int grade[maxn];


int build(int root,int left,int right)
{
    int mid;
    tree[root].left=left;
    tree[root].right=right;
    //已经是最下面了
    if(left==right)
    {
        return tree[root].max=grade[left];
    }
    mid=(left+right)/2;

    int x,y;
    x=build(2*root,left,mid);//左子树
    y=build(2*root+1,mid+1,right);//右子树

    return tree[root].max=x>y?x:y;
}

int query(int root,int left,int right)
{
    //不在区间
    if(tree[root].left>right||tree[root].right<left)
        return 0;
    //包含区间那可以结束了
    if(tree[root].left>=left&&tree[root].right<=right)
        return tree[root].max;

    int x,y;
    x=query(root*2,left,right);
    y=query(root*2+1,left,right);

    return x>y?x:y;
}

int update(int root,int num,int value)
{
    //不在区间
    if(tree[root].left>num||tree[root].right<num)
        return 0;
    //找到那个节点
    if(tree[root].left==num&&tree[root].right==num)
        return tree[root].max=value;

    int x,y;
    x=update(root*2,num,value);
    y=update(root*2+1,num,value);

    return tree[root].max=x>y?x:y;
}



int main()
{
    int n,m,a,b;
    char op;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&grade[i]);
        }
        build(1,1,n);
        for(int i=1;i<=m;i++)
        {
            getchar();
            scanf("%c%d%d",&op,&a,&b);
            if(op=='Q')
            {
                printf("%d\n",query(1,a,b));
            }
            else
            {
                grade[a]=b;
                update(1,a,b);
            }
        }
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值