📌  相关文章
📜  给定数组的索引范围[L,R]中的按位OR查询(1)

📅  最后修改于: 2023-12-03 15:41:17.252000             🧑  作者: Mango

给定数组的索引范围[L,R]中的按位OR查询

在进行查询数组中给定索引范围内元素的按位OR时,可以使用线段树或者树状数组等数据结构来实现,这里我们以线段树为例。

首先定义一个结构体 Node,用于表示线段树中的每个节点。该结构体包含三个成员变量:left 表示左节点的索引,right 表示右节点的索引,value 存储区间内的值的按位OR结果。

struct Node {
    int left;
    int right;
    int value;
};

接下来定义线段树的构建函数 build,该函数接收四个参数:arr 表示原始数组,tree 表示线段树,index 表示当前节点的索引,leftright 则为当前节点表示的区间的左右边界。

void build(int* arr, Node* tree, int index, int left, int right) {
    tree[index].left = left;
    tree[index].right = right;
    if (left == right) {
        tree[index].value = arr[left];
        return;
    }
    int mid = left + (right - left) / 2;
    build(arr, tree, index * 2, left, mid);
    build(arr, tree, index * 2 + 1, mid + 1, right);
    tree[index].value = tree[index * 2].value | tree[index * 2 + 1].value;
}

在构建完线段树后,可以用 query 函数来查询给定索引范围内数组元素的按位OR值。该函数接收五个参数:tree 表示线段树,index 表示当前节点的索引,leftright 为当前节点表示的区间的左右边界,LR 则是查询的索引范围。

int query(Node* tree, int index, int left, int right, int L, int R) {
    if (left >= L && right <= R) {
        return tree[index].value;
    }
    int mid = left + (right - left) / 2;
    int res = 0;
    if (L <= mid) {
        res |= query(tree, index * 2, left, mid, L, R);
    }
    if (R > mid) {
        res |= query(tree, index * 2 + 1, mid + 1, right, L, R);
    }
    return res;
}

参考实现如下:

#include <iostream>

using namespace std;

struct Node {
    int left;
    int right;
    int value;
};

void build(int* arr, Node* tree, int index, int left, int right) {
    tree[index].left = left;
    tree[index].right = right;
    if (left == right) {
        tree[index].value = arr[left];
        return;
    }
    int mid = left + (right - left) / 2;
    build(arr, tree, index * 2, left, mid);
    build(arr, tree, index * 2 + 1, mid + 1, right);
    tree[index].value = tree[index * 2].value | tree[index * 2 + 1].value;
}

int query(Node* tree, int index, int left, int right, int L, int R) {
    if (left >= L && right <= R) {
        return tree[index].value;
    }
    int mid = left + (right - left) / 2;
    int res = 0;
    if (L <= mid) {
        res |= query(tree, index * 2, left, mid, L, R);
    }
    if (R > mid) {
        res |= query(tree, index * 2 + 1, mid + 1, right, L, R);
    }
    return res;
}

int main() {
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int n = sizeof(arr) / sizeof(int);

    // 构建线段树
    Node* tree = new Node[4 * n];
    build(arr, tree, 1, 0, n - 1);

    // 查询索引范围内元素的按位OR值
    int L = 3, R = 7;
    int res = query(tree, 1, 0, n - 1, L, R);
    cout << "arr[" << L << "..." << R << "] OR: " << res << endl;

    return 0;
}

输出结果:

arr[3...7] OR: 127

综上所述,通过线段树实现给定数组的索引范围[L,R]中的按位OR查询,能够有效地提高查询效率,减小时间复杂度。