HDU 1754

(中文题意)

第二道线段树。同样是水题。

但是一开始我把线段树区间段代表的数字简单理解成各个区间的数字的和。但是这道题让我知道这个数组记录的数字是根据需要定义的。

本题区间段记录的是该区间段的最大值。

#include<stdio.h>
#include<iostream>
using namespace std;
int newcha,subb,maxx;
int max(int a,int b)
{
    if(a>b)
        return a;
    return b;
}
struct tr
{
    int l,r,gra;
};
tr me[200000*3+1000];
int tmp[200050];
void build(int s,int e,int k)
{
    me[k].l=s;
    me[k].r=e;
    if(s==e)
    {
        me[k].gra=tmp[s];
        return;
    }
    int m=(s+e)>>1;
    build(s,m,k<<1);
    build(m+1,e,k<<1|1);
    me[k].gra=max(me[k<<1].gra,me[k<<1|1].gra);
}
void chan(int a,int k)
{
    if(me[k].l==me[k].r)
    {
        subb=newcha-me[k].gra;
        me[k].gra=newcha;
        return;
    }
    int m=(me[k].l+me[k].r)>>1;
    if(a>m)
    {
        chan(a,k<<1|1);
    }
    else
    {
        chan(a,k<<1);
    }
    me[k].gra=max(me[k<<1].gra,me[k<<1|1].gra);
}
void unit()
{
    int x;
    scanf("%d%d",&x,&newcha);
    chan(x,1);
}
void ma(int s,int e,int k)
{
    if(e==me[k].r&&s==me[k].l)
    {
        if(maxx<me[k].gra)
        {
            maxx=me[k].gra;
        }
        return;
    }
    int m=(me[k].l+me[k].r)>>1;
    if(s<=m&&e>m)
    {
        ma(s,m,k<<1);
        ma(m+1,e,k<<1|1);
    }
    else if(e<=m)
    {
        ma(s,e,k<<1);
    }
    else if(s>m)
    {
        ma(s,e,k<<1|1);
    }
}
void que()
{
    int x,y;
    maxx=-1;
    scanf("%d%d",&x,&y);
    ma(x,y,1);
    printf("%d
",maxx);
}
int main()
{
    int n,m,i,j;
    char typ[5];
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        getchar();
        for(i=1;i<=n;i++)
        {
            scanf("%d",&tmp[i]);
        }
        getchar();
        build(1,n,1);
        for(i=1;i<=m;i++)
        {
            scanf("%s",typ);
            if(typ[0]=='U')
            {
                unit();
            }
            else if(typ[0]=='Q')
            {
                que();
            }
            getchar();
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/tun117/p/4523981.html