hdu 1754 简单的线段树

这个题目是比较简单的线段树,不过还是想说几句。这个线段树涉及到的操作有建树(这不是废话吗,线段树怎么能不建树呢!),还有就是更新和询问操作。为了节省时间,我们可以把非叶子节点可以用来记录这个区间的最大分数,如果访问到这个区间,直接输出最大分数值就可以了,不必要每次都询问到叶子节点。更新就得说一下了。我写成这样root==id程序就不能运行,但是写成tree[root].l==id&&tree[root].r==id就可以得出结果了,还有就是,你要更新叶子节点的值,还需要执行的一个操作就是从下往上也要更新非叶子节点的值,保持线段树的非叶子节点记录的是区间上的最大值。回溯理解了,那么从下往上的更新也就不难理解。

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 200003
struct SegTree
{
    int l,r,mid;
    int score;
}tree[N*3];
int s[N];
int max(int a,int b)
{
    return a>b?a:b;
}
void BuildTree(int root,int l,int r)
{
    tree[root].l=l;
    tree[root].r=r;
    tree[root].mid=(l+r)/2;
    if(l==r)
    {
        tree[root].score=s[l];
        return ;
    }
    BuildTree(2*root,l,tree[root].mid);
    BuildTree(2*root+1,tree[root].mid+1,r);
    tree[root].score=max(tree[2*root].score,tree[2*root+1].score);
}
int Query(int root,int l,int r)
{
    if(l<=tree[root].l&&tree[root].r<=r)
    {
        return tree[root].score;
    }
    if(tree[root].mid<l)
    {
        return Query(2*root+1,l,r);
    }
    else if(tree[root].mid>=r)
    {
       return Query(2*root,l,r);
    }
    else
    {
        return max(Query(2*root,l,tree[root].mid),Query(2*root+1,tree[root].mid+1,r));
    }
}
void Updata(int root,int id,int key)
{
    if(tree[root].l==id&&tree[root].r==id)
    {
      tree[root].score=key;
      return;
    }
    if(id<=tree[root].mid)
    {
        Updata(2*root,id,key);
    }
    else
    {
        Updata(2*root+1,id,key);
    }
    tree[root].score=max(tree[2*root].score,tree[2*root+1].score);
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&s[i]);
        }
        BuildTree(1,1,n);
        while(m--)
        {
            char ch[3];
            scanf("%s",ch);
            if(ch[0]=='Q')
            {
                int a,b;
                scanf("%d%d",&a,&b);
                printf("%d\n",Query(1,a,b));
            }
            else if(ch[0]=='U')
            {
                int a,b;
                scanf("%d%d",&a,&b);
                Updata(1,a,b);
            }
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值