树状数组求区间最大值

   一直用 线段树 求区间最大值,想换种思路,用树状数组试试,肯定是可以的。

 

首先要对 树状数组的每个 所管理的区间有一定的理解。详见上篇博客: 树状数组(BIT)

 

如图, A数组表示的时输入的数组, C 是树状数组,

树状数组 C[i] 所包含的区间时 [ i - lowbit(i) + 1, i], 其中区间的个数是 lowbit(i) 个, C[i] 一定包含A[i]

之后就可以像 线段树一样进行区间更新和查询操作了.需要更新(查询)子区间就更新(查询)子区间,需要更新(查询)父结点就更新(查询)父结点,

HDU1754 为例, 代码如下:

//Author LJH
//www.cnblogs.com/tenlee
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#define clc(a, b) memset(a, b, sizeof(a))
#define LL long long
using namespace std;

const int inf = 0x3f;
const int INF = 0x3f3f3f3f;
const int maxn = 1e6+5;

int a[maxn], c[maxn];
int n, m;

int lowbit(int x)
{
    return x & (-x);
}

void Build(int id, int val)
{
    a[id] = val;
    while(id <= n)
    {
        c[id] = max(c[id], val);
        id += lowbit(id);
    }
}

void Update(int id, int val)
{
    a[id] = val;
    int i = id, j, k;
    while(i <= n)
    {
        c[i] = a[i];
        if(lowbit(i) > 1) //c[i] 包含区间内元素个数
        {
            k = i - lowbit(i) + 1; // c[i] 所包含区间的左端点
            j = i - 1;
            while(j >= k) //向下查找
            {
                c[i] = max(c[i], c[j]);
                j -= lowbit(j);
            }
        } 
        i += lowbit(i); //向上更新
    }
}

int Query(int ll, int rr)
{
    int ans = a[rr];
    while(true)
    {
        ans = max(ans, a[rr]);
        if(ll == rr) break;

        rr--; //一定要先减
        while(rr-ll >= lowbit(rr)) //向下查询子区间
        {
            ans = max(ans, c[rr]);
            rr -= lowbit(rr);
        }
    }
    return ans;
}

int main()
{
    int x, y;
    char op;
    while(~scanf("%d %d",&n, &m))
    {
        clc(c, 0);
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
            Build(i, a[i]);
        }
        while(m--)
        {
            scanf(" %c %d %d", &op, &x, &y);
            if(op == 'Q')
            {
                printf("%d\n", Query(x, y));
            }
            else
            {
                Update(x, y);
            }
        }
    }
    return 0;
}

 

 原文链接: http://sbp810050504.blog.51cto.com/2799422/1051811

posted @ 2015-09-02 22:03  豪气干云  阅读(1682)  评论(0编辑  收藏  举报