[HDU 1754]I Hate It[树状数组查询+更新区间最大值]

题目链接:[HDU 1754]I Hate It[树状数组查询+更新区间最大值]

题意分析:

查询区间最大值+更新区间最大值。

解题思路:

自己做主把代码改得自己好理解点了XD具体见代码注释

个人感受:

嘛,一步步来,先啃了树状数组先。

具体代码如下:

#include<iostream>
#include<cstdio>
using namespace std;

const int MAXN = 2e5 + 111;

int maxVal[MAXN], a[MAXN];

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

void init(int n)
{
    for (int i = 1; i <= n; ++i)
    {
        scanf("%d", &a[i]);
        maxVal[i] = a[i];
        for (int j = 1; j < lowbit(i); j <<= 1)  // 与所有涉及到的子区间段最大值比较
        {
            maxVal[i] = max(maxVal[i], maxVal[i - j]);
        }
    }
}

int getMax(int l, int r)
{
    int ret = a[r];
    while (l != r)
    {
        for (r -= 1; r - lowbit(r) >= l; r -= lowbit(r)) // 1.判断是区间是否在查询范围内
        {
            ret = max(ret, maxVal[r]);
        }
        ret = max(ret, a[r]); // 2.如果不在查询范围内,则只能将第r个数加入判断
    }
    return ret;
}

void update(int x, int val, int n) // 单单改变父亲结点是不够的,因为无法确定这段区间中的最大值来自哪里,
{                                  // 所以还需要与子区间进行比较确定最大值
    a[x] = val;
    for (int i = x; i <= n; i += lowbit(i))
    {
        maxVal[i] = a[i];
        for (int j = 1; j < lowbit(i); j <<= 1)
        {
            maxVal[i] = max(maxVal[i], maxVal[i - j]);
        }
    }
}


int main()
{
    int n, m, a, b;
    while (~scanf("%d%d", &n, &m))
    {
        init(n);
        char op[2];
        for (int i = 0; i < m; ++i)
        {
            scanf("%s%d%d", op, &a, &b);
            if (op[0] == 'Q') printf("%d\n", getMax(a, b));
            else update(a, b, n);
        }
    }
    return 0;
}



你可能感兴趣的:(树状数组)