HDU--1754 区间最值(树状数组做法)

Posted liyexin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU--1754 区间最值(树状数组做法)相关的知识,希望对你有一定的参考价值。

地址:http://acm.hdu.edu.cn/showproblem.php?pid=1754

技术图片

技术图片

 

     解析:先说update操作。c[]表示所管辖的区间范围里的最大值。

void update(int id,int x)
{
    while(id<=n)
    {
        c[id]=x;
        for(int i=1;i<lowbit(id);i+=lowbit(i))
        {
            c[id]=max(c[id],c[id-i]);
        }
        id+=lowbit(id);
    }
}

    由于加入了一个新值,所以直接改变c[]是没有问题的。看这个for。举个例子:id=8,i=1,2,4。c[8]分别和c[4],c[6]c[7]进行了max更新,所以这个 id-i,是把所有id以内的区间进行了更新,覆盖了所有i<=id的数,很巧妙~。这个例子看这个图更是一目了然了:

技术图片

 

    接下来是query操作:

 

int query(int l,int r)
{
    int md=0;
    while(l<=r)
    {
        md=max(md,a[r]);
        r--;
        for(;r-l>=lowbit(r);r-=lowbit(r))
        {
            md=max(md,c[r]);
        }
    }
    return md;
}

 

    对于r来讲,它所管辖的有lowbit(r)个区间。所以对于[l,r]如果r-l>=lowbit(r),那么c[r]可以直接拿来用。而如果lowbit(r)超出了[l,r],那么就r--对L进行逼近。

    Ac代码:

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
int c[maxn],a[maxn],n,m;
int lowbit(int x)
{
    return x&(-x);
}
void update(int id,int x)
{
    while(id<=n)
    {
        c[id]=x;
        for(int i=1;i<lowbit(id);i+=lowbit(i))
        {
            c[id]=max(c[id],c[id-i]);
        }
        id+=lowbit(id);
    }
}
int query(int l,int r)
{
    int md=0;
    while(l<=r)
    {
        md=max(md,a[r]);
        r--;
        for(;r-l>=lowbit(r);r-=lowbit(r))
        {
            md=max(md,c[r]);
        }
    }
    return md;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
            c[i]=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            update(i,a[i]);
        }
        char ch[12];
        while(m--)
        {
            scanf("%s",ch);
            if(ch[0]==Q)
            {
                int l,r;
                scanf("%d%d",&l,&r);
                cout<<query(l,r)<<endl;
            }
            else
            {
                int id,x;
                scanf("%d%d",&id,&x);
                a[id]=x;
                update(id,x);
            }
        }
    }
} 

 

以上是关于HDU--1754 区间最值(树状数组做法)的主要内容,如果未能解决你的问题,请参考以下文章

HDU-1754 I Hate It (树状数组模板题——单点更新,区间查询最大值)

HDU 1754区间最值 & SPLAY

HDU 1754(线段树区间最值)

HDU - 1754 I Hate It (线段树区间求最值)

HDU 1754 I Hate It(线段树单点更新区间查询最值)

HDU 1754 I Hate It(线段树之单点更新,区间最值)