热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

带有更新查询的二进制数组中第kth组位的索引

带有更新查询的二进制数组中第kth组位的索引原文:https

带有更新查询的二进制数组中第 kth 组位的索引

原文:https://www . geeksforgeeks . org/index-of-kth-set-bit-in-a-a-array-with-update-query/

给定二进制数组 arr[]q 以下类型的查询:


  1. k: 求数组中 k 组位k 1 的索引。

  2. (x,y): 更新 arr[x] = y ,其中 y 可以是 01

例:

输入: arr[] = {1,0,1,0,0,1,1},q = 2
k = 4
(x,y) = (5,1)
输出:
第 4 组位的索引:6
数组更新后:
1 0 1 0 0 1

方法:一个简单的解决方案是运行从 0n–1的循环,并找到 k th 1 。要更新一个值,只需执行 arr[i] = x 。第一次操作需要 O(n) 时间,第二次操作需要 O(1) 时间。
另一种解决方案是创建另一个数组,并将每个 1 的索引存储在该数组中的第 1 个索引处。Kth1的索引现在可以在 O(1) 时间计算,但是更新操作现在需要 O(n) 时间。如果查询操作的数量很大,并且更新很少,这种方法就能很好地工作。
但是,如果查询和更新的次数相等呢?我们可以使用 段树O(Logn) 时间执行这两个操作。

线段树的表示:


  1. 叶节点是输入数组的元素。

  2. 每个内部节点代表叶节点的总和合并。

树的数组表示用于表示段树。对于索引 I 处的每个节点,左子节点位于索引 2i+1 处,右子节点位于索引 2i+2 处,父节点位于(i-1)/2 处。

以下是上述方法的实现:

C++

// C++ implementation of the approach
#include
using namespace std;
// Function to build the tree
void buildTree(int* tree, int* a, int s, int e, int idx)
{
    // s = starting index
    // e = ending index
    // a = array storing binary string of numbers
    // idx = starting index = 1, for recurring the tree
    if (s == e) {
        // store each element value at the
        // leaf node
        tree[idx] = a[s];
        return;
    }
    int mid = (s + e) / 2;
    // Recurring in two sub portions (left, right)
    // to build the segment tree
    // Calling for the left sub portion
    buildTree(tree, a, s, mid, 2 * idx);
    // Calling for the right sub portion
    buildTree(tree, a, mid + 1, e, 2 * idx + 1);
    // Summing up the number of one's
    tree[idx] = tree[2 * idx] + tree[2 * idx + 1];
    return;
}
// Function to return the index of the query
int queryTree(int* tree, int s, int e, int k, int idx)
{
    // s = starting index
    // e = ending index
    // k = searching for kth bit
    // idx = starting index = 1, for recurring the tree
    // k > number of 1's in a binary string
    if (k > tree[idx])
        return -1;
    // leaf node at which kth 1 is stored
    if (s == e)
        return s;
    int mid = (s + e) / 2;
    // If left sub-tree contains more or equal 1's
    // than required kth 1
    if (tree[2 * idx] >= k)
        return queryTree(tree, s, mid, k, 2 * idx);
    // If left sub-tree contains less 1's than
    // required kth 1 then recur in the right sub-tree
    else
        return queryTree(tree, mid + 1, e, k - tree[2 * idx], 2 * idx + 1);
}
// Function to perform the update query
void updateTree(int* tree, int s, int e, int i, int change, int idx)
{
    // s = starting index
    // e = ending index
    // i = index at which change is to be done
    // change = new changed bit
    // idx = starting index = 1, for recurring the tree
    // Out of bounds request
    if (i e) {
        cout <<"error";
        return;
    }
    // Leaf node of the required index i
    if (s == e) {
        // Replacing the node value with
        // the new changed value
        tree[idx] = change;
        return;
    }
    int mid = (s + e) / 2;
    // If the index i lies in the left sub-tree
    if (i >= s && i <= mid)
        updateTree(tree, s, mid, i, change, 2 * idx);
    // If the index i lies in the right sub-tree
    else
        updateTree(tree, mid + 1, e, i, change, 2 * idx + 1);
    // Merging both left and right sub-trees
    tree[idx] = tree[2 * idx] + tree[2 * idx + 1];
    return;
}
// Function to perform queries
void queries(int* tree, int* a, int q, int p, int k, int change, int n)
{
    int s = 0, e = n - 1, idx = 1;
    if (q == 1) {
        // q = 1 update, p = index at which change
        // is to be done, change = new bit
        a[p] = change;
        updateTree(tree, s, e, p, change, idx);
        cout <<"Array after updation:\n";
        for (int i = 0; i             cout <        cout <<"\n";
    }
    else {
        // q = 0, print kth bit
        cout <<"Index of " <             <    }
}
// Driver code
int main()
{
    int a[] = { 1, 0, 1, 0, 0, 1, 1, 1 };
    int n = sizeof(a) / sizeof(int);
    // Declaring & initializing the tree with
    // maximum possible size of the segment tree
    // and each value initially as 0
    int* tree = new int[4 * n + 1];
    for (int i = 0; i <4 * n + 1; ++i) {
        tree[i] = 0;
    }
    // s and e are the starting and ending
    // indices respectively
    int s = 0, e = n - 1, idx = 1;
    // Build the segment tree
    buildTree(tree, a, s, e, idx);
    // Find index of kth set bit
    int q = 0, p = 0, change = 0, k = 4;
    queries(tree, a, q, p, k, change, n);
    // Update query
    q = 1, p = 5, change = 0;
    queries(tree, a, q, p, k, change, n);
    return 0;
}

Java 语言(一种计算机语言,尤用于创建网站)

// Java implementation of the approach
import java.io.*;
import java.util.*;
class GFG
{
    // Function to build the tree
    static void buildTree(int[] tree, int[] a,
                       int s, int e, int idx)
    {
        // s = starting index
        // e = ending index
        // a = array storing binary string of numbers
        // idx = starting index = 1, for recurring the tree
        if (s == e)
        {
            // store each element value at the
            // leaf node
            tree[idx] = a[s];
            return;
        }
        int mid = (s + e) / 2;
        // Recurring in two sub portions (left, right)
        // to build the segment tree
        // Calling for the left sub portion
        buildTree(tree, a, s, mid, 2 * idx);
        // Calling for the right sub portion
        buildTree(tree, a, mid + 1, e, 2 * idx + 1);
        // Summing up the number of one's
        tree[idx] = tree[2 * idx] + tree[2 * idx + 1];
        return;
    }
    // Function to return the index of the query
    static int queryTree(int[] tree, int s,
                        int e, int k, int idx)
    {
        // s = starting index
        // e = ending index
        // k = searching for kth bit
        // idx = starting index = 1, for recurring the tree
        // k > number of 1's in a binary string
        if (k > tree[idx])
            return -1;
        // leaf node at which kth 1 is stored
        if (s == e)
            return s;
        int mid = (s + e) / 2;
        // If left sub-tree contains more or equal 1's
        // than required kth 1
        if (tree[2 * idx] >= k)
            return queryTree(tree, s, mid, k, 2 * idx);
        // If left sub-tree contains less 1's than
        // required kth 1 then recur in the right sub-tree
        else
            return queryTree(tree, mid + 1, e, k - tree[2 * idx],
                                                    2 * idx + 1);
    }
    // Function to perform the update query
    static void updateTree(int[] tree, int s, int e,
                            int i, int change, int idx)
    {
        // s = starting index
        // e = ending index
        // i = index at which change is to be done
        // change = new changed bit
        // idx = starting index = 1, for recurring the tree
        // Out of bounds request
        if (i e)
        {
            System.out.println("Error");
            return;
        }
        // Leaf node of the required index i
        if (s == e)
        {
            // Replacing the node value with
            // the new changed value
            tree[idx] = change;
            return;
        }
        int mid = (s + e) / 2;
        // If the index i lies in the left sub-tree
        if (i >= s && i <= mid)
            updateTree(tree, s, mid, i, change, 2 * idx);
        // If the index i lies in the right sub-tree
        else
            updateTree(tree, mid + 1, e, i, change, 2 * idx + 1);
        // Merging both left and right sub-trees
        tree[idx] = tree[2 * idx] + tree[2 * idx + 1];
        return;
    }
    // Function to perform queries
    static void queries(int[] tree, int[] a, int q, int p,
                                int k, int change, int n)
    {
        int s = 0, e = n - 1, idx = 1;
        if (q == 1)
        {
            // q = 1 update, p = index at which change
            // is to be done, change = new bit
            a[p] = change;
            updateTree(tree, s, e, p, change, idx);
            System.out.println("Array after updation:");
            for (int i = 0; i                 System.out.print(a[i] + " ");
            System.out.println();
        }
        else
        {
            // q = 0, print kth bit
            System.out.printf("Index of %dth set bit: %d\n",
                                k, queryTree(tree, s, e, k, idx));
        }
    }
    // Driver Code
    public static void main(String[] args)
    {
        int[] a = { 1, 0, 1, 0, 0, 1, 1, 1 };
        int n = a.length;
        // Declaring & initializing the tree with
        // maximum possible size of the segment tree
        // and each value initially as 0
        int[] tree = new int[4 * n + 1];
        for (int i = 0; i <4 * n + 1; ++i)
        {
            tree[i] = 0;
        }
        // s and e are the starting and ending
        // indices respectively
        int s = 0, e = n - 1, idx = 1;
        // Build the segment tree
        buildTree(tree, a, s, e, idx);
        // Find index of kth set bit
        int q = 0, p = 0, change = 0, k = 4;
        queries(tree, a, q, p, k, change, n);
        // Update query
        q = 1;
        p = 5;
        change = 0;
        queries(tree, a, q, p, k, change, n);
    }
}
// This code is contributed by
// sanjeev2552

Python 3

# Python3 implementation of the approach
# Function to build the tree
def buildTree(tree: list, a: list,
                s: int, e: int, idx: int):
    # s = starting index
    # e = ending index
    # a = array storing binary string of numbers
    # idx = starting index = 1, for recurring the tree
    if s == e:
        # store each element value at the
        # leaf node
        tree[idx] = a[s]
        return
    mid = (s + e) // 2
    # Recurring in two sub portions (left, right)
    # to build the segment tree
    # Calling for the left sub portion
    buildTree(tree, a, s, mid, 2 * idx)
    # Calling for the right sub portion
    buildTree(tree, a, mid + 1, e, 2 * idx + 1)
    # Summing up the number of one's
    tree[idx] = tree[2 * idx] + tree[2 * idx + 1]
    return
# Function to return the index of the query
def queryTree(tree: list, s: int, e: int,
            k: int, idx: int) -> int:
    # s = starting index
    # e = ending index
    # k = searching for kth bit
    # idx = starting index = 1, for recurring the tree
    # k > number of 1's in a binary string
    if k > tree[idx]:
        return -1
    # leaf node at which kth 1 is stored
    if s == e:
        return s
    mid = (s + e) // 2
    # If left sub-tree contains more or equal 1's
    # than required kth 1
    if tree[2 * idx] >= k:
        return queryTree(tree, s, mid, k, 2 * idx)
    # If left sub-tree contains less 1's than
    # required kth 1 then recur in the right sub-tree
    else:
        return queryTree(tree, mid + 1, e,
                    k - tree[2 * idx], 2 * idx + 1)
# Function to perform the update query
def updateTree(tree: list, s: int, e: int,
                i: int, change: int, idx: int):
    # s = starting index
    # e = ending index
    # i = index at which change is to be done
    # change = new changed bit
    # idx = starting index = 1, for recurring the tree
    # Out of bounds request
    if i e:
        print("error")
        return
    # Leaf node of the required index i
    if s == e:
        # Replacing the node value with
        # the new changed value
        tree[idx] = change
        return
    mid = (s + e) // 2
    # If the index i lies in the left sub-tree
    if i >= s and i <= mid:
        updateTree(tree, s, mid, i, change, 2 * idx)
    # If the index i lies in the right sub-tree
    else:
        updateTree(tree, mid + 1, e, i, change, 2 * idx + 1)
    # Merging both left and right sub-trees
    tree[idx] = tree[2 * idx] + tree[2 * idx + 1]
    return
# Function to perform queries
def queries(tree: list, a: list, q: int, p: int,
            k: int, change: int, n: int):
    s = 0
    e = n - 1
    idx = 1
    if q == 1:
        # q = 1 update, p = index at which change
        # is to be done, change = new bit
        a[p] = change
        updateTree(tree, s, e, p, change, idx)
        print("Array after updation:")
        for i in range(n):
            print(a[i], end=" ")
        print()
    else:
        # q = 0, print kth bit
        print("Index of %dth set bit: %d" % (k,
                queryTree(tree, s, e, k, idx)))
# Driver Code
if __name__ == "__main__":
    a = [1, 0, 1, 0, 0, 1, 1, 1]
    n = len(a)
    # Declaring & initializing the tree with
    # maximum possible size of the segment tree
    # and each value initially as 0
    tree = [0] * (4 * n + 1)
    # s and e are the starting and ending
    # indices respectively
    s = 0
    e = n - 1
    idx = 1
    # Build the segment tree
    buildTree(tree, a, s, e, idx)
    # Find index of kth set bit
    q = 0
    p = 0
    change = 0
    k = 4
    queries(tree, a, q, p, k, change, n)
    # Update query
    q = 1
    p = 5
    change = 0
    queries(tree, a, q, p, k, change, n)
# This code is contributed by
# sanjeev2552

C

// C# implementation of the approach
using System;
class GFG
{
    // Function to build the tree
    static void buildTree(int[] tree, int[] a,
                        int s, int e, int idx)
    {
        // s = starting index
        // e = ending index
        // a = array storing binary string of numbers
        // idx = starting index = 1, for recurring the tree
        if (s == e)
        {
            // store each element value at the
            // leaf node
            tree[idx] = a[s];
            return;
        }
        int mid = (s + e) / 2;
        // Recurring in two sub portions (left, right)
        // to build the segment tree
        // Calling for the left sub portion
        buildTree(tree, a, s, mid, 2 * idx);
        // Calling for the right sub portion
        buildTree(tree, a, mid + 1, e, 2 * idx + 1);
        // Summing up the number of one's
        tree[idx] = tree[2 * idx] + tree[2 * idx + 1];
        return;
    }
    // Function to return the index of the query
    static int queryTree(int[] tree, int s,
                        int e, int k, int idx)
    {
        // s = starting index
        // e = ending index
        // k = searching for kth bit
        // idx = starting index = 1, for recurring the tree
        // k > number of 1's in a binary string
        if (k > tree[idx])
            return -1;
        // leaf node at which kth 1 is stored
        if (s == e)
            return s;
        int mid = (s + e) / 2;
        // If left sub-tree contains more or equal 1's
        // than required kth 1
        if (tree[2 * idx] >= k)
            return queryTree(tree, s, mid, k, 2 * idx);
        // If left sub-tree contains less 1's than
        // required kth 1 then recur in the right sub-tree
        else
            return queryTree(tree, mid + 1,
                            e, k - tree[2 * idx],
                            2 * idx + 1);
    }
    // Function to perform the update query
    static void updateTree(int[] tree, int s, int e,
                            int i, int change, int idx)
    {
        // s = starting index
        // e = ending index
        // i = index at which change is to be done
        // change = new changed bit
        // idx = starting index = 1, for recurring the tree
        // Out of bounds request
        if (i e)
        {
            Console.WriteLine("Error");
            return;
        }
        // Leaf node of the required index i
        if (s == e)
        {
            // Replacing the node value with
            // the new changed value
            tree[idx] = change;
            return;
        }
        int mid = (s + e) / 2;
        // If the index i lies in the left sub-tree
        if (i >= s && i <= mid)
            updateTree(tree, s, mid, i,
                        change, 2 * idx);
        // If the index i lies in the right sub-tree
        else
            updateTree(tree, mid + 1, e, i,
                       change, 2 * idx + 1);
        // Merging both left and right sub-trees
        tree[idx] = tree[2 * idx] +
                    tree[2 * idx + 1];
        return;
    }
    // Function to perform queries
    static void queries(int[] tree, int[] a, int q, int p,
                                int k, int change, int n)
    {
        int s = 0, e = n - 1, idx = 1;
        if (q == 1)
        {
            // q = 1 update, p = index at which change
            // is to be done, change = new bit
            a[p] = change;
            updateTree(tree, s, e, p, change, idx);
            Console.WriteLine("Array after updation:");
            for (int i = 0; i                 Console.Write(a[i] + " ");
            Console.WriteLine();
        }
        else
        {
            // q = 0, print kth bit
            Console.Write("Index of {0}th set bit: {1}\n",
                            k, queryTree(tree, s, e, k, idx));
        }
    }
    // Driver Code
    public static void Main(String[] args)
    {
        int[] a = { 1, 0, 1, 0, 0, 1, 1, 1 };
        int n = a.Length;
        // Declaring & initializing the tree with
        // maximum possible size of the segment tree
        // and each value initially as 0
        int[] tree = new int[4 * n + 1];
        for (int i = 0; i <4 * n + 1; ++i)
        {
            tree[i] = 0;
        }
        // s and e are the starting and ending
        // indices respectively
        int s = 0, e = n - 1, idx = 1;
        // Build the segment tree
        buildTree(tree, a, s, e, idx);
        // Find index of kth set bit
        int q = 0, p = 0, change = 0, k = 4;
        queries(tree, a, q, p, k, change, n);
        // Update query
        q = 1;
        p = 5;
        change = 0;
        queries(tree, a, q, p, k, change, n);
    }
}
// This code is contributed by Rajput-Ji

java 描述语言


Output: 

Index of 4th set bit: 6
Array after updation:
1 0 1 0 0 0 1 1

时间复杂度:每个查询 O(logN),构建段树 O(NlogN)。
辅助空间: O(N)


推荐阅读
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文为Codeforces 1294A题目的解析,主要讨论了Collecting Coins整除+不整除问题。文章详细介绍了题目的背景和要求,并给出了解题思路和代码实现。同时提供了在线测评地址和相关参考链接。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • 成功安装Sabayon Linux在thinkpad X60上的经验分享
    本文分享了作者在国庆期间在thinkpad X60上成功安装Sabayon Linux的经验。通过修改CHOST和执行emerge命令,作者顺利完成了安装过程。Sabayon Linux是一个基于Gentoo Linux的发行版,可以将电脑快速转变为一个功能强大的系统。除了作为一个live DVD使用外,Sabayon Linux还可以被安装在硬盘上,方便用户使用。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • C++中的三角函数计算及其应用
    本文介绍了C++中的三角函数的计算方法和应用,包括计算余弦、正弦、正切值以及反三角函数求对应的弧度制角度的示例代码。代码中使用了C++的数学库和命名空间,通过赋值和输出语句实现了三角函数的计算和结果显示。通过学习本文,读者可以了解到C++中三角函数的基本用法和应用场景。 ... [详细]
author-avatar
顾玉妙
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有