树状数组维护单点修改、区间查询最大值

概述

用一个数组s来存放原始数组,用数组tree来存树状数组。
每次单点修改,都将受影响的s和tree的值修改,时间复杂度为O(logn).
每次区间查询[l,r]的最大值,如果区间长度大于lowbit(r)就一次性跨越一个lowbit(r)来查询,否则就一个点一个点的跨越。把查询过程看作砍柴:
砍一个点、砍一段区间(砍完至少剩一个点)、砍一段区间、砍一段区间…、
剩下的部分不足一段区间+一个点的时,一个点一个点的砍。
砍一个区间用tree,砍一个点用s。

单点修改

//将第i位的值修改为d
void update(int i,int d)
{
    s[i]=d;//修改第i位的值
    while(i<=N)//修改tree数组中的值
    {
        tree[i]=max(tree[i],d);
        i+=lowbit(i);
    }
}

区间查询最大值

//查询区间[l,r]的最大值
int query(int l,int r)
{
    int ans=s[r];//砍一个点
    while(l!=r)
    {
        //剩余部分够一个区间+一个点
        for(--r;r>=l+lowbit(r);r-=lowbit(r))
        {
            ans=max(ans,tree[r]);//砍一个区间
        }
        //剩余部分不够一个区间+一个点
        ans=max(ans,s[r]);//一个点一个点的砍直到r=l,通过for循环中--r去递减。
    }
    return ans;
}

例题

//HDU1754
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn=2e5+100;
int tree[maxn],s[maxn],N;

int lowbit(int i)
{
    return i&(-i);
}
void update(int i,int d)
{
    s[i]=d;
    while(i<=N)
    {
        tree[i]=max(tree[i],d);
        i+=lowbit(i);
    }
}
int query(int l,int r)
{
    int ans=s[r];
    while(l!=r)
    {
        for(--r;r>=l+lowbit(r);r-=lowbit(r))
        {
            ans=max(ans,tree[r]);
        }
        ans=max(ans,s[r]);
    }
    return ans;
}
int main()
{
    int M;
    while(~scanf("%d%d",&N,&M))
    {
        memset(s,0,sizeof(s));
        memset(tree,0,sizeof(tree));
        for(int i=1;i<=N;i++)
        {
            int a;
            scanf("%d",&a);
            s[i]=a;
            update(i,a);
        }
        while(M--)
        {
            char C[10];
            int x,y;
            scanf("%s%d%d",C,&x,&y);
            if(C[0]=='Q') printf("%d\n",query(x,y));
            else update(x,y);
        }
    }
    return 0;

}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值