Número de elementos menores o iguales a un número dado en un subarreglo dado | Conjunto 2 (incluidas las actualizaciones)

Dada una array ‘a[]’ y un número de consultas q habrá dos tipos de consultas

  1. Actualización de consulta 0 (i, v): dos números enteros i y v, lo que significa establecer a [i] = v
  2. Consulta 1 cuenta (l, r, k): Necesitamos imprimir el número de enteros menores que iguales a k en el subarreglo l a r.

Dado a[i], v <= 10000 Ejemplos:

Input : arr[] = {5, 1, 2, 3, 4}
        q = 6
        1 1 3 1  // First value 1 means type of query is count()
        0 3 10   // First value 0 means type of query is update()
        1 3 3 4
        0 2 1
        0 0 2
        1 0 4 5
Output :
1
0
4
For first query number of values less than equal to 1 in 
arr[1..3] is 1(1 only), update a[3] = 10
There is no value less than equal to 4 in the a[3..3]
and similarly other queries are answered       

Hemos discutido una solución que maneja solo consultas de recuento() en la publicación a continuación. Número de elementos menores o iguales a un número dado en un subarreglo dado Aquí también se debe manejar la consulta update(). Enfoque ingenuo El enfoque ingenuo es siempre que haya una operación de actualización, actualice la array y siempre que haya una consulta de tipo 2, atraviese el subarreglo y cuente los elementos válidos. Enfoque eficiente La idea es utilizar la descomposición de la raíz cuadrada 

  1. Paso 1: divida la array en bloques de igual tamaño sqrt (n). Para cada bloque, mantenga un árbol de índice binario de tamaño igual a 1 más que el elemento máximo posible en la array de elementos de ese bloque.
  2. Paso 2: para cada elemento de la array, busque el bloque al que pertenece y actualice la array de bits de ese bloque con el valor 1 en arr[i].
  3. Paso 3: siempre que haya una consulta de actualización, actualice la array de bits del bloque correspondiente en el valor original de la array en ese índice con valor igual a -1 y actualice la array de bits del mismo bloque con valor 1 en el nuevo valor de la array en ese índice.
  4. Paso 4: para la consulta de tipo 2, puede realizar una sola consulta al BIT (para contar elementos menores o iguales a k) para cada bloque completo en el rango, y para los dos bloques parciales al final, simplemente recorra los elementos .

C++

// Number of elements less than or equal to a given
// number in a given subarray and allowing update
// operations.
#include<bits/stdc++.h>
using namespace std;
 
const int MAX = 10001;
 
// updating the bit array of a valid block
void update(int idx, int blk, int val, int bit[][MAX])
{
    for (; idx<MAX; idx += (idx&-idx))
        bit[blk][idx] += val;
}
 
// answering the query
int query(int l, int r, int k, int arr[], int blk_sz,
                                      int bit[][MAX])
{
    // traversing the first block in range
    int sum = 0;
    while (l<r && l%blk_sz!=0 && l!=0)
    {
        if (arr[l] <= k)
            sum++;
        l++;
    }
 
    // Traversing completely overlapped blocks in
    // range for such blocks bit array of that block
    // is queried
    while (l + blk_sz <= r)
    {
        int idx = k;
        for (; idx > 0 ; idx -= idx&-idx)
            sum += bit[l/blk_sz][idx];
        l += blk_sz;
    }
 
    // Traversing the last block
    while (l <= r)
    {
        if (arr[l] <= k)
            sum++;
        l++;
    }
    return sum;
}
 
// Preprocessing the array
void preprocess(int arr[], int blk_sz, int n, int bit[][MAX])
{
    for (int i=0; i<n; i++)
        update(arr[i], i/blk_sz, 1, bit);
}
 
void preprocessUpdate(int i, int v, int blk_sz,
                      int arr[], int bit[][MAX])
{
    // updating the bit array at the original
    // and new value of array
    update(arr[i], i/blk_sz, -1, bit);
    update(v, i/blk_sz, 1, bit);
    arr[i] = v;
}
 
// driver function
int main()
{
    int arr[] = {5, 1, 2, 3, 4};
    int n = sizeof(arr)/sizeof(arr[0]);
 
    // size of block size will be equal to square root of n
    int blk_sz = sqrt(n);
 
    // initialising bit array of each block
    // as elements of array cannot exceed 10^4 so size
    // of bit array is accordingly
    int bit[blk_sz+1][MAX];
    memset(bit, 0, sizeof(bit));
 
    preprocess(arr, blk_sz, n, bit);
    cout << query  (1, 3, 1, arr, blk_sz, bit) << endl;
 
    preprocessUpdate(3, 10, blk_sz, arr, bit);
    cout << query(3, 3, 4, arr, blk_sz, bit) << endl;
    preprocessUpdate(2, 1, blk_sz, arr, bit);
    preprocessUpdate(0, 2, blk_sz, arr, bit);
    cout << query (0, 4, 5, arr, blk_sz, bit) << endl;
    return 0;
}

Java

// Number of elements less than or equal to a given
// number in a given subarray and allowing update
// operations.
 
class Test
{
    static final int MAX = 10001;
     
    // updating the bit array of a valid block
    static void update(int idx, int blk, int val, int bit[][])
    {
        for (; idx<MAX; idx += (idx&-idx))
            bit[blk][idx] += val;
    }
      
    // answering the query
    static int query(int l, int r, int k, int arr[], int blk_sz,
                                          int bit[][])
    {
        // traversing the first block in range
        int sum = 0;
        while (l<r && l%blk_sz!=0 && l!=0)
        {
            if (arr[l] <= k)
                sum++;
            l++;
        }
      
        // Traversing completely overlapped blocks in
        // range for such blocks bit array of that block
        // is queried
        while (l + blk_sz <= r)
        {
            int idx = k;
            for (; idx > 0 ; idx -= idx&-idx)
                sum += bit[l/blk_sz][idx];
            l += blk_sz;
        }
      
        // Traversing the last block
        while (l <= r)
        {
            if (arr[l] <= k)
                sum++;
            l++;
        }
        return sum;
    }
      
    // Preprocessing the array
    static void preprocess(int arr[], int blk_sz, int n, int bit[][])
    {
        for (int i=0; i<n; i++)
            update(arr[i], i/blk_sz, 1, bit);
    }
      
    static void preprocessUpdate(int i, int v, int blk_sz,
                          int arr[], int bit[][])
    {
        // updating the bit array at the original
        // and new value of array
        update(arr[i], i/blk_sz, -1, bit);
        update(v, i/blk_sz, 1, bit);
        arr[i] = v;
    }
     
    // Driver method
    public static void main(String args[])
    {
        int arr[] = {5, 1, 2, 3, 4};
      
        // size of block size will be equal to square root of n
        int blk_sz = (int) Math.sqrt(arr.length);
      
        // initialising bit array of each block
        // as elements of array cannot exceed 10^4 so size
        // of bit array is accordingly
        int bit[][] = new int[blk_sz+1][MAX];
      
        preprocess(arr, blk_sz, arr.length, bit);
        System.out.println(query(1, 3, 1, arr, blk_sz, bit));
      
        preprocessUpdate(3, 10, blk_sz, arr, bit);
        System.out.println(query(3, 3, 4, arr, blk_sz, bit));
        preprocessUpdate(2, 1, blk_sz, arr, bit);
        preprocessUpdate(0, 2, blk_sz, arr, bit);
        System.out.println(query (0, 4, 5, arr, blk_sz, bit));
    }
}

Python3

# Number of elements less than or equal to a given
# number in a given subarray and allowing update
# operations.
MAX = 10001
 
# updating the bit array of a valid block
def update(idx, blk, val, bit):
    while idx < MAX:
        bit[blk][idx] += val
 
        idx += (idx & -idx)
 
# answering the query
def query(l, r, k, arr, blk_sz, bit):
 
    # traversing the first block in range
    summ = 0
    while l < r and l % blk_sz != 0 and l != 0:
        if arr[l] <= k:
            summ += 1
        l += 1
 
    # Traversing completely overlapped blocks in
    # range for such blocks bit array of that block
    # is queried
    while l + blk_sz <= r:
        idx = k
        while idx > 0:
            summ += bit[l // blk_sz][idx]
            idx -= (idx & -idx)
 
        l += blk_sz
 
    # Traversing the last block
    while l <= r:
        if arr[l] <= k:
            summ += 1
        l += 1
 
    return summ
 
# Preprocessing the array
def preprocess(arr, blk_sz, n, bit):
    for i in range(n):
        update(arr[i], i // blk_sz, 1, bit)
 
def preprocessUpdate(i, v, blk_sz, arr, bit):
 
    # updating the bit array at the original
    # and new value of array
    update(arr[i], i // blk_sz, -1, bit)
    update(v, i // blk_sz, 1, bit)
    arr[i] = v
 
# Driver Code
if __name__ == "__main__":
    arr = [5, 1, 2, 3, 4]
    n = len(arr)
 
    # size of block size will be equal
    # to square root of n
    from math import sqrt
    blk_sz = int(sqrt(n))
 
    # initialising bit array of each block
    # as elements of array cannot exceed 10^4
    # so size of bit array is accordingly
    bit = [[0 for i in range(MAX)]
              for j in range(blk_sz + 1)]
 
    preprocess(arr, blk_sz, n, bit)
    print(query(1, 3, 1, arr, blk_sz, bit))
 
    preprocessUpdate(3, 10, blk_sz, arr, bit)
    print(query(3, 3, 4, arr, blk_sz, bit))
    preprocessUpdate(2, 1, blk_sz, arr, bit)
    preprocessUpdate(0, 2, blk_sz, arr, bit)
    print(query(0, 4, 5, arr, blk_sz, bit))
 
# This code is contributed by
# sanjeev2552

C#

// Number of elements less than or equal
// to a given number in a given subarray
// and allowing update operations.
using System;
         
class GFG
{
    static int MAX = 10001;
     
    // updating the bit array of a valid block
    static void update(int idx, int blk,
                    int val, int [,]bit)
    {
        for (; idx < MAX; idx += (idx&-idx))
            bit[blk, idx] += val;
    }
     
    // answering the query
    static int query(int l, int r, int k, int []arr,
                             int blk_sz, int [,]bit)
    {
        // traversing the first block in range
        int sum = 0;
        while (l < r && l % blk_sz != 0 && l != 0)
        {
            if (arr[l] <= k)
                sum++;
            l++;
        }
     
        // Traversing completely overlapped blocks in
        // range for such blocks bit array of that block
        // is queried
        while (l + blk_sz <= r)
        {
            int idx = k;
            for (; idx > 0 ; idx -= idx&-idx)
                sum += bit[l/blk_sz,idx];
            l += blk_sz;
        }
     
        // Traversing the last block
        while (l <= r)
        {
            if (arr[l] <= k)
                sum++;
            l++;
        }
        return sum;
    }
     
    // Preprocessing the array
    static void preprocess(int []arr, int blk_sz,
                               int n, int [,]bit)
    {
        for (int i=0; i<n; i++)
            update(arr[i], i / blk_sz, 1, bit);
    }
     
    static void preprocessUpdate(int i, int v, int blk_sz,
                                    int []arr, int [,]bit)
    {
        // updating the bit array at the original
        // and new value of array
        update(arr[i], i/blk_sz, -1, bit);
        update(v, i/blk_sz, 1, bit);
        arr[i] = v;
    }
     
    // Driver method
    public static void Main()
    {
        int []arr = {5, 1, 2, 3, 4};
     
        // size of block size will be
        // equal to square root of n
        int blk_sz = (int) Math.Sqrt(arr.Length);
     
        // initialising bit array of each block
        // as elements of array cannot exceed 10^4 so size
        // of bit array is accordingly
        int [,]bit = new int[blk_sz+1,MAX];
     
        preprocess(arr, blk_sz, arr.Length, bit);
        Console.WriteLine(query(1, 3, 1, arr, blk_sz, bit));
     
        preprocessUpdate(3, 10, blk_sz, arr, bit);
        Console.WriteLine(query(3, 3, 4, arr, blk_sz, bit));
        preprocessUpdate(2, 1, blk_sz, arr, bit);
        preprocessUpdate(0, 2, blk_sz, arr, bit);
        Console.WriteLine(query (0, 4, 5, arr, blk_sz, bit));
    }
}
 
// This code is contributed by Sam007

Javascript

<script>
 
// Number of elements less than or equal to a given
// number in a given subarray and allowing update
// operations.
 
const MAX = 10001;
 
// updating the bit array of a valid block
function update(idx, blk, val, bit)
{
    while(idx<MAX)
    {
        bit[blk][idx] += val;
        idx += (idx&-idx);
    }
}
   
// answering the query
function query(l, r,  k,  arr,  blk_sz, bit)
{
    // traversing the first block in range
    var sum = 0;
    while (l<r && l%blk_sz!=0 && l!=0)
    {
        if (arr[l] <= k)
            sum++;
        l++;
    }
   
    // Traversing completely overlapped blocks in
    // range for such blocks bit array of that block
    // is queried
    while (l + blk_sz <= r)
    {
        var idx = k;
        for (; idx > 0 ; idx -= idx&-idx)
            sum += bit[parseInt(l/blk_sz)][idx];
        l += blk_sz;
    }
   
    // Traversing the last block
    while (l <= r)
    {
        if (arr[l] <= k)
            sum++;
        l++;
    }
    return sum;
}
   
// Preprocessing the array
function preprocess(arr,  blk_sz,  n,  bit)
{
    for (var i=0; i<n; i++)
        update(arr[i], parseInt(i/blk_sz), 1, bit);
}
   
function preprocessUpdate( i,  v,  blk_sz,
                       arr,  bit)
{
    // updating the bit array at the original
    // and new value of array
    update(arr[i], parseInt(i/blk_sz), -1, bit);
    update(v, parseInt(i/blk_sz), 1, bit);
    arr[i] = v;
}
 
// Driver code
 
// Test Case 1
let arr = [ 5, 1, 2, 3, 4 ];
var n = arr.length;
// size of block size will be equal to square root of n
var blk_sz = parseInt(Math.sqrt(n));
 
// initialising bit array of each block
// as elements of array cannot exceed 10^4 so size
// of bit array is accordingly
var bit = new Array(blk_sz+1);
 
for (var i = 0; i < bit.length; i++)
{
  bit[i] = new Array(MAX);
}
for (let i = 0; i < bit.length; i++)
{
  for (let j = 0; j < MAX; j++)
  {
    bit[i][j] = 0;
    }
}
 
preprocess(arr, blk_sz, n, bit);
document.write(query  (1, 3, 1, arr, blk_sz, bit));
document.write("<br>");
 
preprocessUpdate(3, 10, blk_sz, arr, bit);
document.write(query(3, 3, 4, arr, blk_sz, bit));
document.write("<br>");
preprocessUpdate(2, 1, blk_sz, arr, bit);
preprocessUpdate(0, 2, blk_sz, arr, bit);
document.write(query (0, 4, 5, arr, blk_sz, bit));
document.write("<br>");       
 
// This code is contributed by Aarti_Rathi
 
</script>

Producción:

1
0
4

La pregunta es saber por qué no usar este método cuando no hubo operaciones de actualización. La respuesta radica en la complejidad del espacio. En este método, se usa una array de bits 2-d y su tamaño depende del valor máximo posible de la array, pero cuando había ninguna operación de actualización, nuestra array de bits solo dependía del tamaño de la array. Este artículo es una contribución de Ayush Jha . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks. Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 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 *