Encuentra el conteo de números distintos en un rango

Dada una array de tamaño N que contiene números solo del 0 al 63, y se le solicitan consultas Q al respecto.
Las consultas son las siguientes: 
 

  • 1 XY, es decir, cambiar el elemento en el índice X a Y
  • 2 LR, es decir, imprime el recuento de distintos elementos presentes entre L y R inclusive

Ejemplos: 
 

Input:
N = 7
ar = {1, 2, 1, 3, 1, 2, 1}
Q = 5
{ {2, 1, 4},
  {1, 4, 2},
  {1, 5, 2},
  {2, 4, 6},
  {2, 1, 7} }
Output:
3
1
2

Input:
N = 15
ar = {4, 6, 3, 2, 2, 3, 6, 5, 5, 5, 4, 2, 1, 5, 1}
Q = 5
{ {1, 6, 5},
  {1, 4, 2},
  {2, 6, 14},
  {2, 6, 8},
  {2, 1, 6} };

Output:
5
2
5

Requisitos previos: árbol de segmentos y enfoque de manipulación de bits  
:
 

  • La máscara de bits formada en la pregunta denotará la presencia o no del i-ésimo número, descubriremos que al verificar el i-ésimo bit de nuestra máscara de bits, si el i-ésimo bit está activado, eso significa que el i-ésimo elemento está presente; de ​​lo contrario, no está presente.
  • Cree un árbol de segmentos clásico y cada uno de sus Nodes contendrá una máscara de bits que se utiliza para decodificar la cantidad de elementos distintos en ese segmento en particular que está definido por el Node en particular.
  • Cree el árbol de segmentos de forma ascendente, por lo tanto, la máscara de bits para el Node actual del árbol de segmentos se puede calcular fácilmente realizando una operación OR bit a bit en las máscaras de bits del hijo derecho e izquierdo de este Node. Los Nodes hoja se manejarán por separado. La actualización también se realizará de la misma manera.

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

C++

// C++ Program to find the distinct
// elements in a range
#include <bits/stdc++.h>
using namespace std;
 
// Function to perform queries in a range
long long query(int start, int end, int left, int right,
                int node, long long seg[])
{
    // No overlap
    if (end < left || start > right) {
        return 0;
    }
 
    // Totally Overlap
    else if (start >= left && end <= right) {
        return seg[node];
    }
 
    // Partial Overlap
    else {
        int mid = (start + end) / 2;
 
        // Finding the Answer
        // for the left Child
        long long leftChild = query(start, mid, left,
                                    right, 2 * node, seg);
 
        // Finding the Answer
        // for the right Child
        long long rightChild = query(mid + 1, end, left,
                                     right, 2 * node + 1, seg);
 
        // Combining the BitMasks
        return (leftChild | rightChild);
    }
}
 
// Function to perform update operation
// in the Segment seg
void update(int left, int right, int index, int Value,
            int node, int ar[], long long seg[])
{
    if (left == right) {
        ar[index] = Value;
 
        // Forming the BitMask
        seg[node] = (1LL << Value);
        return;
    }
 
    int mid = (left + right) / 2;
    if (index > mid) {
 
        // Updating the left Child
        update(mid + 1, right, index, Value, 2 * node + 1, ar, seg);
    }
    else {
 
        // Updating the right Child
        update(left, mid, index, Value, 2 * node, ar, seg);
    }
 
    // Updating the BitMask
    seg[node] = (seg[2 * node] | seg[2 * node + 1]);
}
 
// Building the Segment Tree
void build(int left, int right, int node, int ar[],
           long long seg[])
{
    if (left == right) {
 
        // Building the Initial BitMask
        seg[node] = (1LL << ar[left]);
 
        return;
    }
 
    int mid = (left + right) / 2;
 
    // Building the left seg tree
    build(left, mid, 2 * node, ar, seg);
 
    // Building the right seg tree
    build(mid + 1, right, 2 * node + 1, ar, seg);
 
    // Forming the BitMask
    seg[node] = (seg[2 * node] | seg[2 * node + 1]);
}
 
// Utility Function to answer the queries
void getDistinctCount(vector<vector<int> >& queries,
                      int ar[], long long seg[], int n)
{
 
    for (int i = 0; i < queries.size(); i++) {
 
        int op = queries[i][0];
 
        if (op == 2) {
 
            int l = queries[i][1], r = queries[i][2];
 
            long long tempMask = query(0, n - 1, l - 1,
                                       r - 1, 1, seg);
 
            int countOfBits = 0;
 
            // Counting the set bits which denote the
            // distinct elements
            for (int i = 63; i >= 0; i--) {
 
                if (tempMask & (1LL << i)) {
 
                    countOfBits++;
                }
            }
 
            cout << countOfBits << '\n';
        }
        else {
 
            int index = queries[i][1];
            int val = queries[i][2];
 
            // Updating the value
            update(0, n - 1, index - 1, val, 1, ar, seg);
        }
    }
}
 
// Driver Code
int main()
{
    int n = 7;
    int ar[] = { 1, 2, 1, 3, 1, 2, 1 };
 
    long long seg[4 * n] = { 0 };
    build(0, n - 1, 1, ar, seg);
 
    int q = 5;
    vector<vector<int> > queries = {
        { 2, 1, 4 },
        { 1, 4, 2 },
        { 1, 5, 2 },
        { 2, 4, 6 },
        { 2, 1, 7 }
    };
 
    getDistinctCount(queries, ar, seg, n);
 
    return 0;
}

Java

// Java Program to find the distinct
// elements in a range
import java.util.*;
 
class GFG{
  
// Function to perform queries in a range
static long query(int start, int end, int left, int right,
                int node, long seg[])
{
    // No overlap
    if (end < left || start > right) {
        return 0;
    }
  
    // Totally Overlap
    else if (start >= left && end <= right) {
        return seg[node];
    }
  
    // Partial Overlap
    else {
        int mid = (start + end) / 2;
  
        // Finding the Answer
        // for the left Child
        long leftChild = query(start, mid, left,
                                    right, 2 * node, seg);
  
        // Finding the Answer
        // for the right Child
        long rightChild = query(mid + 1, end, left,
                                     right, 2 * node + 1, seg);
  
        // Combining the BitMasks
        return (leftChild | rightChild);
    }
}
  
// Function to perform update operation
// in the Segment seg
static void update(int left, int right, int index, int Value,
            int node, int ar[], long seg[])
{
    if (left == right) {
        ar[index] = Value;
  
        // Forming the BitMask
        seg[node] = (1L << Value);
        return;
    }
  
    int mid = (left + right) / 2;
    if (index > mid) {
  
        // Updating the left Child
        update(mid + 1, right, index, Value, 2 * node + 1, ar, seg);
    }
    else {
  
        // Updating the right Child
        update(left, mid, index, Value, 2 * node, ar, seg);
    }
  
    // Updating the BitMask
    seg[node] = (seg[2 * node] | seg[2 * node + 1]);
}
  
// Building the Segment Tree
static void build(int left, int right, int node, int ar[],
           long seg[])
{
    if (left == right) {
  
        // Building the Initial BitMask
        seg[node] = (1L << ar[left]);
  
        return;
    }
  
    int mid = (left + right) / 2;
  
    // Building the left seg tree
    build(left, mid, 2 * node, ar, seg);
  
    // Building the right seg tree
    build(mid + 1, right, 2 * node + 1, ar, seg);
  
    // Forming the BitMask
    seg[node] = (seg[2 * node] | seg[2 * node + 1]);
}
  
// Utility Function to answer the queries
static void getDistinctCount(int  [][]queries,
                      int ar[], long seg[], int n)
{
  
    for (int i = 0; i < queries.length; i++) {
  
        int op = queries[i][0];
  
        if (op == 2) {
  
            int l = queries[i][1], r = queries[i][2];
  
            long tempMask = query(0, n - 1, l - 1,
                                       r - 1, 1, seg);
  
            int countOfBits = 0;
  
            // Counting the set bits which denote the
            // distinct elements
            for (int s = 63; s >= 0; s--) {
  
                if ((tempMask & (1L << s))>0) {
  
                    countOfBits++;
                }
            }
  
            System.out.println(countOfBits);
        }
        else {
  
            int index = queries[i][1];
            int val = queries[i][2];
  
            // Updating the value
            update(0, n - 1, index - 1, val, 1, ar, seg);
        }
    }
}
  
// Driver Code
public static void main(String[] args)
{
    int n = 7;
    int ar[] = { 1, 2, 1, 3, 1, 2, 1 };
  
    long seg[] = new long[4 * n];
    build(0, n - 1, 1, ar, seg);
  
    int [][]queries = {
        { 2, 1, 4 },
        { 1, 4, 2 },
        { 1, 5, 2 },
        { 2, 4, 6 },
        { 2, 1, 7 }
    };
  
    getDistinctCount(queries, ar, seg, n);
  
}
}
 
// This code is contributed by PrinciRaj1992

Python3

# Python3 Program to find the distinct
# elements in a range
 
# Function to perform queries in a range
def query(start, end, left,
          right, node, seg):
     
    # No overlap
    if (end < left or start > right):
        return 0
 
    # Totally Overlap
    elif (start >= left and
            end <= right):
        return seg[node]
 
    # Partial Overlap
    else:
        mid = (start + end) // 2
 
        # Finding the Answer
        # for the left Child
        leftChild = query(start, mid, left,
                          right, 2 * node, seg)
 
        # Finding the Answer
        # for the right Child
        rightChild = query(mid + 1, end, left,
                           right, 2 * node + 1, seg)
 
        # Combining the BitMasks
        return (leftChild | rightChild)
 
# Function to perform update operation
# in the Segment seg
def update(left, right, index,
           Value, node, ar, seg):
    if (left == right):
        ar[index] = Value
 
        # Forming the BitMask
        seg[node] = (1 << Value)
        return
 
    mid = (left + right) // 2
    if (index > mid):
 
        # Updating the left Child
        update(mid + 1, right, index,
               Value, 2 * node + 1, ar, seg)
    else:
 
        # Updating the right Child
        update(left, mid, index,
               Value, 2 * node, ar, seg)
 
    # Updating the BitMask
    seg[node] = (seg[2 * node] |
                 seg[2 * node + 1])
 
# Building the Segment Tree
def build(left, right, node, ar, eg):
 
    if (left == right):
 
        # Building the Initial BitMask
        seg[node] = (1 << ar[left])
 
        return
 
    mid = (left + right) // 2
 
    # Building the left seg tree
    build(left, mid, 2 * node, ar, seg)
 
    # Building the right seg tree
    build(mid + 1, right,
                2 * node + 1, ar, seg)
 
    # Forming the BitMask
    seg[node] = (seg[2 * node] |
                 seg[2 * node + 1])
 
# Utility Function to answer the queries
def getDistinctCount(queries, ar, seg, n):
 
    for i in range(len(queries)):
 
        op = queries[i][0]
 
        if (op == 2):
 
            l = queries[i][1]
            r = queries[i][2]
 
            tempMask = query(0, n - 1, l - 1,
                             r - 1, 1, seg)
 
            countOfBits = 0
 
            # Counting the set bits which denote
            # the distinct elements
            for i in range(63, -1, -1):
 
                if (tempMask & (1 << i)):
 
                    countOfBits += 1
 
            print(countOfBits)
        else:
 
            index = queries[i][1]
            val = queries[i][2]
 
            # Updating the value
            update(0, n - 1, index - 1,
                       val, 1, ar, seg)
 
# Driver Code
if __name__ == '__main__':
    n = 7
    ar = [1, 2, 1, 3, 1, 2, 1]
 
    seg = [0] * 4 * n
    build(0, n - 1, 1, ar, seg)
 
    q = 5
    queries = [[ 2, 1, 4 ],
               [ 1, 4, 2 ],
               [ 1, 5, 2 ],
               [ 2, 4, 6 ],
               [ 2, 1, 7 ]]
 
    getDistinctCount(queries, ar, seg, n)
 
# This code is contributed by Mohit Kumar

C#

// C# Program to find the distinct
// elements in a range
using System;
 
class GFG{
   
// Function to perform queries in a range
static long query(int start, int end, int left, int right,
                int node, long []seg)
{
    // No overlap
    if (end < left || start > right) {
        return 0;
    }
   
    // Totally Overlap
    else if (start >= left && end <= right) {
        return seg[node];
    }
   
    // Partial Overlap
    else {
        int mid = (start + end) / 2;
   
        // Finding the Answer
        // for the left Child
        long leftChild = query(start, mid, left,
                                    right, 2 * node, seg);
   
        // Finding the Answer
        // for the right Child
        long rightChild = query(mid + 1, end, left,
                                     right, 2 * node + 1, seg);
   
        // Combining the BitMasks
        return (leftChild | rightChild);
    }
}
   
// Function to perform update operation
// in the Segment seg
static void update(int left, int right, int index, int Value,
            int node, int []ar, long []seg)
{
    if (left == right) {
        ar[index] = Value;
   
        // Forming the BitMask
        seg[node] = (1L << Value);
        return;
    }
   
    int mid = (left + right) / 2;
    if (index > mid) {
   
        // Updating the left Child
        update(mid + 1, right, index, Value, 2 * node + 1, ar, seg);
    }
    else {
   
        // Updating the right Child
        update(left, mid, index, Value, 2 * node, ar, seg);
    }
   
    // Updating the BitMask
    seg[node] = (seg[2 * node] | seg[2 * node + 1]);
}
   
// Building the Segment Tree
static void build(int left, int right, int node, int []ar,
           long []seg)
{
    if (left == right) {
   
        // Building the Initial BitMask
        seg[node] = (1L << ar[left]);
   
        return;
    }
   
    int mid = (left + right) / 2;
   
    // Building the left seg tree
    build(left, mid, 2 * node, ar, seg);
   
    // Building the right seg tree
    build(mid + 1, right, 2 * node + 1, ar, seg);
   
    // Forming the BitMask
    seg[node] = (seg[2 * node] | seg[2 * node + 1]);
}
   
// Utility Function to answer the queries
static void getDistinctCount(int  [,]queries,
                      int []ar, long []seg, int n)
{
   
    for (int i = 0; i < queries.GetLength(0); i++) {
   
        int op = queries[i,0];
   
        if (op == 2) {
   
            int l = queries[i,1], r = queries[i,2];
   
            long tempMask = query(0, n - 1, l - 1,
                                       r - 1, 1, seg);
   
            int countOfBits = 0;
   
            // Counting the set bits which denote the
            // distinct elements
            for (int s = 63; s >= 0; s--) {
   
                if ((tempMask & (1L << s))>0) {
   
                    countOfBits++;
                }
            }
   
            Console.WriteLine(countOfBits);
        }
        else {
   
            int index = queries[i,1];
            int val = queries[i,2];
   
            // Updating the value
            update(0, n - 1, index - 1, val, 1, ar, seg);
        }
    }
}
   
// Driver Code
public static void Main(String[] args)
{
    int n = 7;
    int []ar = { 1, 2, 1, 3, 1, 2, 1 };
   
    long []seg = new long[4 * n];
    build(0, n - 1, 1, ar, seg);
   
    int [,]queries = {
        { 2, 1, 4 },
        { 1, 4, 2 },
        { 1, 5, 2 },
        { 2, 4, 6 },
        { 2, 1, 7 }
    };
   
    getDistinctCount(queries, ar, seg, n);
   
}
}
 
// This code is contributed by 29AjayKumar
Producción: 

3
1
2

 

Complejidad del tiempo: O(N + Q*Log(N))
 

Publicación traducida automáticamente

Artículo escrito por Raunaq Singh 3 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 *