📌  相关文章
📜  在将给定的数组分成两半后,使用K位循环移位,使用按位或来查找数组总和

📅  最后修改于: 2021-04-17 11:11:06             🧑  作者: Mango

给定长度为N数组A [] ,其中N为偶数,任务是回答Q个独立的查询,其中每个查询由一个正整数K组成,该整数表示对该数组执行的循环移位次数,并查找元素的总和通过对分割后的数组执行按位或运算。
注意:每个查询均以原始数组开头。
例子:

天真的方法:
要解决上述问题,最简单的方法是将数组的每个元素移动K%(N / 2) ,然后遍历数组以为每个查询计算两半的OR。但是这种方法效率不高,因此可以进一步优化。
高效方法:
为了优化上述方法,我们可以借助细分树数据结构。

以下是解决问题的步骤:

  • 为原始数组A []构造一个段树,并分配一个变量,假设i = K%(N / 2)
  • 然后,对于每个查询,我们使用查找按位OR的段树;即按位从第一(N / 2)的端部按位或I元素或– I – 1个元件。
  • 然后计算范围为[(N / 2)– i,N – i – 1]的元素的按位或。
  • 将两个结果相加以获得第i个查询的答案。

下面是上述方法的实现:

C++
// C++ Program to find Bitwise OR of two
// equal halves of an array after performing
// K right circular shifts
#include 
const int MAX = 100005;
using namespace std;
 
// Array for storing
// the segment tree
int seg[4 * MAX];
 
// Function to build the segment tree
void build(int node, int l, int r, int a[])
{
    if (l == r)
        seg[node] = a[l];
 
    else {
        int mid = (l + r) / 2;
 
        build(2 * node, l, mid, a);
        build(2 * node + 1, mid + 1, r, a);
 
        seg[node] = (seg[2 * node]
                     | seg[2 * node + 1]);
    }
}
 
// Function to return the OR
// of elements in the range [l, r]
int query(int node, int l, int r,
          int start, int end, int a[])
{
    // Check for out of bound condition
    if (l > end or r < start)
        return 0;
 
    if (start <= l and r <= end)
        return seg[node];
 
    // Find middle of the range
    int mid = (l + r) / 2;
 
    // Recurse for all the elements in array
    return ((query(2 * node, l, mid,
                   start, end, a))
            | (query(2 * node + 1, mid + 1,
                     r, start, end, a)));
}
 
// Function to find the OR sum
void orsum(int a[], int n, int q, int k[])
{
    // Function to build the segment Tree
    build(1, 0, n - 1, a);
 
    // Loop to handle q queries
    for (int j = 0; j < q; j++) {
        // Effective number of
        // right circular shifts
        int i = k[j] % (n / 2);
 
        // Calculating the OR of
        // the two halves of the
        // array from the segment tree
 
        // OR of second half of the
        // array [n/2-i, n-1-i]
        int sec = query(1, 0, n - 1,
                        n / 2 - i, n - i - 1, a);
 
        // OR of first half of the array
        // [n-i, n-1]OR[0, n/2-1-i]
        int first = (query(1, 0, n - 1, 0,
                           n / 2 - 1 - i, a)
                     | query(1, 0, n - 1,
                             n - i, n - 1, a));
 
        int temp = sec + first;
 
        // Print final answer to the query
        cout << temp << endl;
    }
}
 
// Driver Code
int main()
{
 
    int a[] = { 7, 44, 19, 86, 65, 39, 75, 101 };
    int n = sizeof(a) / sizeof(a[0]);
 
    int q = 2;
 
    int k[q] = { 4, 2 };
 
    orsum(a, n, q, k);
 
    return 0;
}


Java
// Java program to find Bitwise OR of two
// equal halves of an array after performing
// K right circular shifts
import java.util.*;
 
class GFG{
     
static int MAX = 100005;
 
// Array for storing
// the segment tree
static int []seg = new int[4 * MAX];
 
// Function to build the segment tree
static void build(int node, int l,
                  int r, int a[])
{
    if (l == r)
        seg[node] = a[l];
 
    else
    {
        int mid = (l + r) / 2;
 
        build(2 * node, l, mid, a);
        build(2 * node + 1, mid + 1, r, a);
 
        seg[node] = (seg[2 * node] |
                     seg[2 * node + 1]);
    }
}
 
// Function to return the OR
// of elements in the range [l, r]
static int query(int node, int l, int r,
                 int start, int end, int a[])
{
     
    // Check for out of bound condition
    if (l > end || r < start)
        return 0;
 
    if (start <= l && r <= end)
        return seg[node];
 
    // Find middle of the range
    int mid = (l + r) / 2;
 
    // Recurse for all the elements in array
    return ((query(2 * node, l, mid,
                   start, end, a)) |
            (query(2 * node + 1, mid + 1,
                   r, start, end, a)));
}
 
// Function to find the OR sum
static void orsum(int a[], int n,
                  int q, int k[])
{
     
    // Function to build the segment Tree
    build(1, 0, n - 1, a);
 
    // Loop to handle q queries
    for(int j = 0; j < q; j++)
    {
         
        // Effective number of
        // right circular shifts
        int i = k[j] % (n / 2);
 
        // Calculating the OR of
        // the two halves of the
        // array from the segment tree
 
        // OR of second half of the
        // array [n/2-i, n-1-i]
        int sec = query(1, 0, n - 1,
                        n / 2 - i,
                        n - i - 1, a);
 
        // OR of first half of the array
        // [n-i, n-1]OR[0, n/2-1-i]
        int first = (query(1, 0, n - 1, 0,
                           n / 2 - 1 - i, a) |
                     query(1, 0, n - 1,
                           n - i, n - 1, a));
 
        int temp = sec + first;
 
        // Print final answer to the query
        System.out.print(temp + "\n");
    }
}
 
// Driver Code
public static void main(String[] args)
{
 
    int a[] = { 7, 44, 19, 86, 65, 39, 75, 101 };
    int n = a.length;
    int q = 2;
 
    int k[] = { 4, 2 };
 
    orsum(a, n, q, k);
}
}
 
// This code is contributed by 29AjayKumar


Python3
# Python3 program to find Bitwise OR of two
# equal halves of an array after performing
# K right circular shifts
MAX = 100005
 
# Array for storing
# the segment tree
seg = [0] * (4 * MAX)
 
# Function to build the segment tree
def build(node, l, r, a):
 
    if (l == r):
        seg[node] = a[l]
 
    else:
        mid = (l + r) // 2
 
        build(2 * node, l, mid, a)
        build(2 * node + 1, mid + 1, r, a)
         
        seg[node] = (seg[2 * node] |
                     seg[2 * node + 1])
 
# Function to return the OR
# of elements in the range [l, r]
def query(node, l, r, start, end, a):
     
    # Check for out of bound condition
    if (l > end or r < start):
        return 0
 
    if (start <= l and r <= end):
        return seg[node]
 
    # Find middle of the range
    mid = (l + r) // 2
 
    # Recurse for all the elements in array
    return ((query(2 * node, l, mid,
                       start, end, a)) |
            (query(2 * node + 1, mid + 1,
                       r, start, end, a)))
 
# Function to find the OR sum
def orsum(a, n, q, k):
 
    # Function to build the segment Tree
    build(1, 0, n - 1, a)
 
    # Loop to handle q queries
    for j in range(q):
         
        # Effective number of
        # right circular shifts
        i = k[j] % (n // 2)
 
        # Calculating the OR of
        # the two halves of the
        # array from the segment tree
 
        # OR of second half of the
        # array [n/2-i, n-1-i]
        sec = query(1, 0, n - 1, n // 2 - i,
                          n - i - 1, a)
 
        # OR of first half of the array
        # [n-i, n-1]OR[0, n/2-1-i]
        first = (query(1, 0, n - 1, 0,
                             n // 2 -
                             1 - i, a) |
                 query(1, 0, n - 1,
                             n - i,
                             n - 1, a))
 
        temp = sec + first
 
        # Print final answer to the query
        print(temp)
 
# Driver Code
if __name__ == "__main__":
 
    a = [ 7, 44, 19, 86, 65, 39, 75, 101 ]
    n = len(a)
     
    q = 2
    k = [ 4, 2 ]
     
    orsum(a, n, q, k)
 
# This code is contributed by chitranayal


C#
// C# program to find Bitwise OR of two
// equal halves of an array after performing
// K right circular shifts
using System;
class GFG{
     
static int MAX = 100005;
 
// Array for storing
// the segment tree
static int []seg = new int[4 * MAX];
 
// Function to build the segment tree
static void build(int node, int l,
                  int r, int []a)
{
    if (l == r)
        seg[node] = a[l];
 
    else
    {
        int mid = (l + r) / 2;
 
        build(2 * node, l, mid, a);
        build(2 * node + 1, mid + 1, r, a);
 
        seg[node] = (seg[2 * node] |
                     seg[2 * node + 1]);
    }
}
 
// Function to return the OR
// of elements in the range [l, r]
static int query(int node, int l, int r,
                 int start, int end, int []a)
{
     
    // Check for out of bound condition
    if (l > end || r < start)
        return 0;
 
    if (start <= l && r <= end)
        return seg[node];
 
    // Find middle of the range
    int mid = (l + r) / 2;
 
    // Recurse for all the elements in array
    return ((query(2 * node, l, mid,
                      start, end, a)) |
            (query(2 * node + 1, mid + 1,
                   r, start, end, a)));
}
 
// Function to find the OR sum
static void orsum(int []a, int n,
                  int q, int []k)
{
     
    // Function to build the segment Tree
    build(1, 0, n - 1, a);
 
    // Loop to handle q queries
    for(int j = 0; j < q; j++)
    {
         
        // Effective number of
        // right circular shifts
        int i = k[j] % (n / 2);
 
        // Calculating the OR of
        // the two halves of the
        // array from the segment tree
 
        // OR of second half of the
        // array [n/2-i, n-1-i]
        int sec = query(1, 0, n - 1,
                        n / 2 - i,
                        n - i - 1, a);
 
        // OR of first half of the array
        // [n-i, n-1]OR[0, n/2-1-i]
        int first = (query(1, 0, n - 1, 0,
                         n / 2 - 1 - i, a) |
                    query(1, 0, n - 1,
                          n - i, n - 1, a));
 
        int temp = sec + first;
 
        // Print readonly answer to the query
        Console.Write(temp + "\n");
    }
}
 
// Driver Code
public static void Main(String[] args)
{
    int []a = { 7, 44, 19, 86, 65, 39, 75, 101 };
    int n = a.Length;
    int q = 2;
 
    int []k = { 4, 2 };
 
    orsum(a, n, q, k);
}
}
 
// This code is contributed by 29AjayKumar


Javascript


输出:
238
230