Consultas para contar elementos de array de un rango dado que tienen un solo bit establecido – Part 1

Dada una array arr[] que consta de N enteros y una array 2D Q[][] que consta de consultas de los siguientes dos tipos:

  • 1 LR: Imprime el conteo de números del rango [L, R] con un solo bit establecido.
  • 2 XV: actualice el elemento de la array en el índice X con V .

Ejemplos:

Entrada: arr[] = { 12, 11, 16, 2, 32 }, Q[][] = { { 1, 0, 2 }, { 2, 4, 24 }, { 1, 1, 4 } }
Salida : 1 2
Explicación:

  • Consulta 1: Imprime el recuento de elementos de la array con un solo bit en el rango de índices [0, 2], es decir, {16}.
  • Consulta 2: Establecer arr[4] = 24 . Por lo tanto, la array arr[] se modifica a {12, 11, 16, 24, 5}.
  • Consulta 3: Imprima el recuento de elementos de array con un solo bit en el rango de índices [1, 4], es decir, {16, 32}.

Entrada: arr[] = { 2, 1, 101, 11, 4 }, Q[][] = { { 1, 2, 4 }, { 2, 4, 12 }, { 1, 2, 4 } }
Salida : 1 0
Explicación:

  • Consulta 1: Imprime el recuento de elementos de la array con un solo bit en el rango de índices [2, 4], es decir, {4}.
  • Consulta 2: establezca arr[4] = 24 , lo que modifica la array a arr[] = { 2, 1, 101, 11, 12}.
  • Consulta 3: imprima el recuento de elementos de array con un solo bit en el rango de índices [2, 4]. Pero ningún elemento de array del rango dado de índices contiene solo un bit.

Enfoque ingenuo: el enfoque más simple es recorrer la array sobre el rango de índices [L, R] para cada consulta y para cada elemento, verificar si tiene exactamente un bit establecido o no. Cuenta de incrementos para cada elemento de la array para el que se encuentra que es verdadero. Después de recorrer todo el rango, imprima el valor de count . Para consultas de tipo 2, simplemente arr[X] = V
Complejidad de tiempo: O(N * Q * log(N))
Espacio auxiliar: O(1)

Enfoque eficiente: el enfoque anterior se puede optimizar utilizando un árbol de segmentos . Siga los pasos a continuación para resolver el problema:

  • Defina una función, marque (S) para verificar si el número entero contiene solo un bit establecido.
  • Inicialice 3 variables: ss, se y si para almacenar el punto inicial del segmento actual, el punto final del segmento actual y el valor del Node actual en el árbol del segmento, respectivamente.
  • Defina una función, digamos build_seg(ss, se, si), para construir un árbol de segmentos Similar al árbol de segmentos de suma , cada Node almacena el recuento de elementos con un solo bit en su subárbol:
    • Si ss == se, árbol[s[i]] = comprobar (arr[ss] )
    • De lo contrario, atraviese el subárbol izquierdo y el subárbol derecho.
    • Ahora, actualice el Node actual como árbol[si] = árbol[2 * si + 1]+ árbol[2 * si + 2].
  • Defina una función, digamos actualizar( ss, se, si, X, V) , para señalar actualizar un valor en la array arr[]:
    • Si el Node actual es un Node hoja, es decir, ss == se , actualice el árbol [si] = comprobar (V).
    • De lo contrario, busque el índice X , es decir, si X ≤ (ss + se) / 2 , luego vaya al subárbol izquierdo, es decir , actualice (ss, mid, 2 * si + 1, X, V). De lo contrario, vaya al subárbol derecho, es decir , actualice (mid + 1, se, 2 * si + 2, X, V).
    • Actualizar el Node actual.
  • Defina una función, digamos consulta (ss, se, si, L, R) para contar números que tienen solo un bit en el rango [L, R]:
    • Verifique si el segmento actual [L, R] no se cruza con [ss, se] y luego devuelva 0.
    • De lo contrario, si ss >= L y se ≤ R , devuelve tree[si] .
    • Si ninguna de las condiciones anteriores satisface, devuelve query(ss, mid, L, R, 2 * si + 1)+query(mid + 1, se, L, R, 2 * si + 2) .
  • Para consultas de tipo { 1, L, R } , imprima la consulta (0, N-1, 0, L, R).
  • Para consultas de tipo { 2, X, V }, actualice el valor en el árbol, actualice (0, N-1, 0, X, V) .

A continuación se muestra la implementación del enfoque anterior:

C++

// C++ implementation
// for above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Check if N has only
// one set bit
bool check(int N)
{
    if (N == 0)
        return 0;
    return !(N & (N - 1));
}
 
// Function to build segment tree
void build_seg_tree(int ss, int se, int si,
                    int tree[], int arr[])
{
    // If se is leaf node
    if (ss == se) {
 
        // Update the node
        tree[si] = check(arr[ss]);
        return;
    }
 
    // Stores mid value of segment [ss, se]
    int mid = (ss + se) / 2;
 
    // Recursive call for left Subtree
    build_seg_tree(ss, mid,
                   2 * si + 1, tree, arr);
 
    // Recursive call for right Subtree
    build_seg_tree(mid + 1, se,
                   2 * si + 2, tree, arr);
 
    // Update the Current Node
    tree[si] = tree[2 * si + 1]
               + tree[2 * si + 2];
}
 
// Function to update a value at Xth index
void update(int ss, int se, int si,
            int X, int V, int tree[], int arr[])
{
 
    if (ss == se) {
 
        // If ss is equal to X
        if (ss == X) {
 
            // Update the Xth node
            arr[X] = V;
 
            // Update the tree
            tree[si] = check(V);
        }
        return;
    }
 
    // Stores the mid of segment [ss, se]
    int mid = (ss + se) / 2;
 
    if (X <= mid)
        update(ss, mid, 2 * si + 1,
               X, V, tree, arr);
    else
        update(mid + 1, se, 2 * si + 2,
               X, V, tree, arr);
 
    // Update current node
    tree[si] = tree[2 * si + 1]
               + tree[2 * si + 2];
}
 
// Count of numbers
// having one set bit
int query(int l, int r, int ss,
          int se, int si, int tree[])
{
    // If L > se or R < ss
    // Invalid Range
    if (r < ss || l > se)
        return 0;
 
    // If [ss, se] lies
    // inside the [L, R]
    if (l <= ss && r >= se)
        return tree[si];
 
    // Stores the mid of segment [ss, se]
    int mid = (ss + se) / 2;
 
    // Return the sum after recursively
    // traversing left and right subtree
    return query(l, r, ss,
                 mid, 2 * si + 1, tree)
           + query(l, r, mid + 1,
                   se, 2 * si + 2, tree);
}
 
// Function to solve queries
void Query(int arr[], int N,
           vector<vector<int> > Q)
{
    // Initialise Segment tree
    int tree[4 * N] = { 0 };
 
    // Build segment tree
    build_seg_tree(0, N - 1, 0, tree, arr);
 
    // Perform queries
    for (int i = 0; i < (int)Q.size(); i++) {
        if (Q[i][0] == 1)
 
            cout << query(Q[i][1], Q[i][2],
                          0, N - 1, 0, tree)
                 << " ";
        else
            update(0, N - 1, 0, Q[i][1], Q[i][2], tree,
                   arr);
    }
}
 
// Driver Code
int main()
{
    // Input
    int arr[] = { 12, 11, 16, 2, 32 };
    vector<vector<int> > Q{ { 1, 0, 2 },
                            { 2, 4, 24 },
                            { 1, 1, 4 } };
    int N = sizeof(arr) / sizeof(arr[0]);
 
    // Function call to
    // solve queries
    Query(arr, N, Q);
 
    return 0;
}

Java

/*package whatever //do not write package name here */
import java.io.*;
class GFG {
 
  // Check if N has only
  // one set bit
  static int check(int N)
  {
    if (Integer.bitCount(N) == 1)
      return 1;
    else
      return 0;
  }
 
  // Function to build segment tree
  static void build_seg_tree(int ss, int se, int si,
                             int tree[], int arr[])
  {
 
    // If se is leaf node
    if (ss == se)
    {
 
      // Update the node
      tree[si] = check(arr[ss]);
      return;
    }
 
    // Stores mid value of segment [ss, se]
    int mid = (ss + se) / 2;
 
    // Recursive call for left Subtree
    build_seg_tree(ss, mid, 2 * si + 1, tree, arr);
 
    // Recursive call for right Subtree
    build_seg_tree(mid + 1, se, 2 * si + 2, tree, arr);
 
    // Update the Current Node
    tree[si] = tree[2 * si + 1] + tree[2 * si + 2];
  }
 
  // Function to update a value at Xth index
  static void update(int ss, int se, int si, int X, int V,
                     int tree[], int arr[])
  {
 
    if (ss == se)
    {
 
      // If ss is equal to X
      if (ss == X)
      {
 
        // Update the Xth node
        arr[X] = V;
 
        // Update the tree
        tree[si] = check(V);
      }
      return;
    }
 
    // Stores the mid of segment [ss, se]
    int mid = (ss + se) / 2;
 
    if (X <= mid)
      update(ss, mid, 2 * si + 1, X, V, tree, arr);
    else
      update(mid + 1, se, 2 * si + 2, X, V, tree,
             arr);
 
    // Update current node
    tree[si] = tree[2 * si + 1] + tree[2 * si + 2];
  }
 
  // Count of numbers
  // having one set bit
  static int query(int l, int r, int ss,
                   int se, int si,
                   int tree[])
  {
    // If L > se or R < ss
    // Invalid Range
    if (r < ss || l > se)
      return 0;
 
    // If [ss, se] lies
    // inside the [L, R]
    if (l <= ss && r >= se)
      return tree[si];
 
    // Stores the mid of segment [ss, se]
    int mid = (ss + se) / 2;
 
    // Return the sum after recursively
    // traversing left and right subtree
    return query(l, r, ss, mid, 2 * si + 1, tree)
      + query(l, r, mid + 1, se, 2 * si + 2, tree);
  }
 
  // Function to solve queries
  static void Query(int arr[], int N, int[][] Q)
  {
    // Initialise Segment tree
    int tree[] = new int[4 * N];
 
    // Build segment tree
    build_seg_tree(0, N - 1, 0, tree, arr);
 
    // Perform queries
    for (int i = 0; i < Q.length; i++) {
      if (Q[i][0] == 1)
 
        System.out.print(query(Q[i][1], Q[i][2], 0,
                               N - 1, 0, tree) + " ");
      else
        update(0, N - 1, 0, Q[i][1], Q[i][2], tree,
               arr);
    }
  }
 
  // Driver Code
  public static void main(String[] args)
  {
 
    int arr[] = { 12, 11, 16, 2, 32 };
    int[][] Q
      = { { 1, 0, 2 }, { 2, 4, 24 }, { 1, 1, 4 } };
    int N = arr.length;
 
    // Function call to
    // solve queries
    Query(arr, N, Q);
  }
}
 
// This code is contributed by hemanthsawarna1506.

Python3

# Python3 implementation of
# the above approach
 
# Check if N has only
# one set bit
def check(N) :
     
    if (N == 0):
        return 0
    return ((N & (N - 1)) == 0)
 
# Function to build segment tree
def build_seg_tree(ss, se, si, tree, arr) :
     
    # If se is leaf node
    if (ss == se) :
 
        # Update the node
        tree[si] = check(arr[ss])
        return
     
    # Stores mid value of segment [ss, se]
    mid = (ss + se) // 2
 
    # Recursive call for left Subtree
    build_seg_tree(ss, mid,
                   2 * si + 1, tree, arr)
 
    # Recursive call for right Subtree
    build_seg_tree(mid + 1, se,
                   2 * si + 2, tree, arr)
 
    # Update the Current Node
    tree[si] = tree[2 * si + 1] + tree[2 * si + 2]
 
# Function to update a value at Xth index
def update(ss, se, si, X, V, tree, arr) :
    if (ss == se) :
 
        # If ss is equal to X
        if (ss == X) :
 
            # Update the Xth node
            arr[X] = V
 
            # Update the tree
            tree[si] = check(V)   
        return
     
    # Stores the mid of segment [ss, se]
    mid = (ss + se) // 2
 
    if (X <= mid):
        update(ss, mid, 2 * si + 1,
               X, V, tree, arr)
    else :
        update(mid + 1, se, 2 * si + 2,
               X, V, tree, arr)
 
    # Update current node
    tree[si] = tree[2 * si + 1] + tree[2 * si + 2]
 
# Count of numbers
# having one set bit
def query(l, r, ss, se, si, tree) :
               
    # If L > se or R < ss
    # Invalid Range
    if (r < ss or l > se):
        return 0
 
    # If [ss, se] lies
    # inside the [L, R]
    if (l <= ss and r >= se):
        return tree[si]
 
    # Stores the mid of segment [ss, se]
    mid = (ss + se) // 2
 
    # Return the sum after recursively
    # traversing left and right subtree
    return (query(l, r, ss, mid, 2 * si + 1, tree) + query(l, r, mid + 1, se, 2 * si + 2, tree))
 
# Function to solve queries
def Query(arr, N, Q) :
     
    # Initialise Segment tree
    tree = [0] * (4 * N)
 
    # Build segment tree
    build_seg_tree(0, N - 1, 0, tree, arr)
 
    # Perform queries
    for i in range(len(Q)):
        if (Q[i][0] == 1):
 
            print(query(Q[i][1], Q[i][2],
                          0, N - 1, 0, tree), end = " ")
        else :
            update(0, N - 1, 0, Q[i][1], Q[i][2], tree, arr)
     
# Driver Code
 
# Input
arr = [ 12, 11, 16, 2, 32 ]
Q = [ [ 1, 0, 2 ], [ 2, 4, 24 ], [ 1, 1, 4 ]] 
N = len(arr)
 
# Function call to
# solve queries
Query(arr, N, Q)
 
# This code is contributed by code_hunt.

C#

// C# implementation
// for above approach
using System;
using System.Collections.Generic;
class GFG
{
 
  // Check if N has only
  // one set bit
  static int check(int N)
  {
    if (N == 0 || (N & (N - 1)) != 0)
      return 0;
 
    return 1;
  }
 
  // Function to build segment tree
  static void build_seg_tree(int ss, int se, int si,
                             int[] tree, int[] arr)
  {
     
    // If se is leaf node
    if (ss == se)
    {
 
      // Update the node
      tree[si] = check(arr[ss]);
      return;
    }
 
    // Stores mid value of segment [ss, se]
    int mid = (ss + se) / 2;
 
    // Recursive call for left Subtree
    build_seg_tree(ss, mid,
                   2 * si + 1, tree, arr);
 
    // Recursive call for right Subtree
    build_seg_tree(mid + 1, se,
                   2 * si + 2, tree, arr);
 
    // Update the Current Node
    tree[si] = tree[2 * si + 1]
      + tree[2 * si + 2];
  }
 
  // Function to update a value at Xth index
  static void update(int ss, int se, int si,
                     int X, int V, int[] tree, int[] arr)
  {
 
    if (ss == se)
    {
 
      // If ss is equal to X
      if (ss == X)
      {
 
        // Update the Xth node
        arr[X] = V;
 
        // Update the tree
        tree[si] = check(V);
      }
      return;
    }
 
    // Stores the mid of segment [ss, se]
    int mid = (ss + se) / 2;
 
    if (X <= mid)
      update(ss, mid, 2 * si + 1,
             X, V, tree, arr);
    else
      update(mid + 1, se, 2 * si + 2,
             X, V, tree, arr);
 
    // Update current node
    tree[si] = tree[2 * si + 1]
      + tree[2 * si + 2];
  }
 
  // Count of numbers
  // having one set bit
  static int query(int l, int r, int ss,
                   int se, int si, int[] tree)
  {
 
    // If L > se or R < ss
    // Invalid Range
    if (r < ss || l > se)
      return 0;
 
    // If [ss, se] lies
    // inside the [L, R]
    if (l <= ss && r >= se)
      return tree[si];
 
    // Stores the mid of segment [ss, se]
    int mid = (ss + se) / 2;
 
    // Return the sum after recursively
    // traversing left and right subtree
    return query(l, r, ss,
                 mid, 2 * si + 1, tree)
      + query(l, r, mid + 1,
              se, 2 * si + 2, tree);
  }
 
  // Function to solve queries
  static void Query(int[] arr, int N,
                    List<List<int> > Q)
  {
 
    // Initialise Segment tree
    int[] tree = new int[4 * N];
 
    // Build segment tree
    build_seg_tree(0, N - 1, 0, tree, arr);
 
    // Perform queries
    for (int i = 0; i < (int)Q.Count; i++)
    {
      if (Q[i][0] == 1)      
        Console.Write(query(Q[i][1], Q[i][2], 0, N - 1, 0, tree) + " ");
      else
        update(0, N - 1, 0, Q[i][1], Q[i][2], tree, arr);
    }
  } 
 
  // Driver code
  static void Main()
  {
 
    // Input
    int[] arr = { 12, 11, 16, 2, 32 };
    List<List<int> > Q = new List<List<int>>();
    Q.Add(new List<int>(new int[]{1, 0, 2}));
    Q.Add(new List<int>(new int[]{2, 4, 24}));
    Q.Add(new List<int>(new int[]{1, 1, 4}));
    int N = arr.Length;
 
    // Function call to
    // solve queries
    Query(arr, N, Q);
  }
}
 
// This code is contributed by divyeshrabadiya07

Javascript

<script>
 
// JavaScript implementation
// for above approach
 
 
// Check if N has only
// one set bit
function check( N)
{
    if (N == 0)
        return 0;
    return !(N & (N - 1));
}
 
// Function to build segment tree
function build_seg_tree( ss,  se,  si, tree, arr)
{
    // If se is leaf node
    if (ss == se) {
 
        // Update the node
        tree[si] = check(arr[ss]);
        return;
    }
 
    // Stores mid value of segment [ss, se]
    var mid = parseInt((ss + se) / 2);
 
    // Recursive call for left Subtree
    build_seg_tree(ss, mid, 2 * si + 1, tree, arr);
 
    // Recursive call for right Subtree
    build_seg_tree(mid + 1, se, 2 * si + 2, tree, arr);
 
    // Update the Current Node
    tree[si] = tree[2 * si + 1] + tree[2 * si + 2];
}
 
// Function to update a value at Xth index
function update(ss, se, si, X, V, tree,  arr)
{
 
    if (ss == se) {
 
        // If ss is equal to X
        if (ss == X) {
 
            // Update the Xth node
            arr[X] = V;
 
            // Update the tree
            tree[si] = check(V);
        }
        return;
    }
 
    // Stores the mid of segment [ss, se]
    var mid = parseInt((ss + se) / 2);
 
    if (X <= mid)
        update(ss, mid, 2 * si + 1, X, V, tree, arr);
    else
        update(mid + 1, se, 2 * si + 2, X, V, tree, arr);
 
    // Update current node
    tree[si] = tree[2 * si + 1] + tree[2 * si + 2];
}
 
// Count of numbers
// having one set bit
function query( l, r, ss, se, si, tree)
{
    // If L > se or R < ss
    // Invalid Range
    if (r < ss || l > se)
        return 0;
 
    // If [ss, se] lies
    // inside the [L, R]
    if (l <= ss && r >= se)
        return tree[si];
 
    // Stores the mid of segment [ss, se]
    var mid = parseInt((ss + se) / 2);
 
    // Return the sum after recursively
    // traversing left and right subtree
    return query(l, r, ss, mid, 2 * si + 1, tree)
           + query(l, r, mid + 1, se, 2 * si + 2, tree);
}
 
// Function to solve queries
function Query(arr, N, Q)
{
    // Initialise Segment tree
    var tree = new Array(4 * N);
    tree.fill( 0 );
 
    // Build segment tree
    build_seg_tree(0, N - 1, 0, tree, arr);
 
    // Perform queries
    for (var i = 0; i < Q.length; i++) {
        if (Q[i][0] == 1)
 
            document.write( query(Q[i][1], Q[i][2],
                          0, N - 1, 0, tree)
                 + " ");
        else
            update(0, N - 1, 0, Q[i][1], Q[i][2], tree,
                   arr);
    }
}
 
var arr = [ 12, 11, 16, 2, 32 ];
var Q = [ [1, 0, 2 ],
          [ 2, 4, 24],
          [ 1, 1, 4 ] ];
    var N = arr.length;
 
    // Function call to
    // solve queries
    Query(arr, N, Q);
 
// This code is contributed by SoumikMondal
 
</script>
Producción: 

1 2

 

Complejidad de tiempo: O(N*log(N)+Q*log(N))
Espacio auxiliar: O(1) 

Publicación traducida automáticamente

Artículo escrito por prakersh009 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *