对二进制数组进行计数和切换查询

给定一个大小n,其中最初所有元素均为0。任务是执行以下两种类型的多个查询。查询可以以任何顺序出现。

null

1.切换(开始、结束): 切换(0到1或1到0)从“开始”到“结束”的值。

2.计数(开始、结束): 计算从“开始”到“结束”的给定范围内的1个数。

Input : n = 5       // we have n = 5 blocks        toggle 1 2  // change 1 into 0 or 0 into 1        Toggle 2 4        Count  2 3  // count all 1's within the range        Toggle 2 4        Count  1 4  // count all 1's within the rangeOutput : Total number of 1's in range 2 to 3 is = 1         Total number of 1's in range 1 to 4 is = 2

A. 简单解决方案 对于这个问题,需要遍历“Toggle”查询的整个范围,当您得到“Count”查询时,然后对给定范围的所有1进行计数。但是这种方法的时间复杂度是O(q*n),其中q=查询总数。 一 有效率的 解决这个问题的方法是使用 分段树 具有 惰性传播 .在这里,我们收集更新,直到我们得到一个“计数”查询。当我们得到“Count”的查询时,我们在数组中进行之前收集的所有切换更新,然后在给定范围内计算1的数量。 以下是上述方法的实施情况:

C++

// C++ program to implement toggle and count
// queries on a binary array.
#include<bits/stdc++.h>
using namespace std;
const int MAX = 100000;
// segment tree to store count of 1's within range
int tree[MAX] = {0};
// bool type tree to collect the updates for toggling
// the values of 1 and 0 in given range
bool lazy[MAX] = { false };
// function for collecting updates of toggling
// node --> index of current node in segment tree
// st --> starting index of current node
// en --> ending index of current node
// us --> starting index of range update query
// ue --> ending index of range update query
void toggle( int node, int st, int en, int us, int ue)
{
// If lazy value is non-zero for current node of segment
// tree, then there are some pending updates. So we need
// to make sure that the pending updates are done before
// making new updates. Because this value may be used by
// parent after recursive calls (See last line of this
// function)
if (lazy[node])
{
// Make pending updates using value stored in lazy nodes
lazy[node] = false ;
tree[node] = en - st + 1 - tree[node];
// checking if it is not leaf node because if
// it is leaf node then we cannot go further
if (st < en)
{
// We can postpone updating children we don't
// need their new values now.
// Since we are not yet updating children of 'node',
// we need to set lazy flags for the children
lazy[node<<1] = !lazy[node<<1];
lazy[1+(node<<1)] = !lazy[1+(node<<1)];
}
}
// out of range
if (st>en || us > en || ue < st)
return ;
// Current segment is fully in range
if (us<=st && en<=ue)
{
// Add the difference to current node
tree[node] = en-st+1 - tree[node];
// same logic for checking leaf node or not
if (st < en)
{
// This is where we store values in lazy nodes,
// rather than updating the segment tree itelf
// Since we don't need these updated values now
// we postpone updates by storing values in lazy[]
lazy[node<<1] = !lazy[node<<1];
lazy[1+(node<<1)] = !lazy[1+(node<<1)];
}
return ;
}
// If not completely in rang, but overlaps, recur for
// children,
int mid = (st+en)/2;
toggle((node<<1), st, mid, us, ue);
toggle((node<<1)+1, mid+1,en, us, ue);
// And use the result of children calls to update this node
if (st < en)
tree[node] = tree[node<<1] + tree[(node<<1)+1];
}
/* node --> Index of current node in the segment tree.
Initially 0 is passed as root is always at'
index 0
st & en  --> Starting and ending indexes of the
segment represented by current node,
i.e., tree[node]
qs & qe  --> Starting and ending indexes of query
range */
// function to count number of 1's within given range
int countQuery( int node, int st, int en, int qs, int qe)
{
// current node is out of range
if (st>en || qs > en || qe < st)
return 0;
// If lazy flag is set for current node of segment tree,
// then there are some pending updates. So we need to
// make sure that the pending updates are done before
// processing the sub sum query
if (lazy[node])
{
// Make pending updates to this node. Note that this
// node represents sum of elements in arr[st..en] and
// all these elements must be increased by lazy[node]
lazy[node] = false ;
tree[node] = en-st+1-tree[node];
// checking if it is not leaf node because if
// it is leaf node then we cannot go further
if (st<en)
{
// Since we are not yet updating children os si,
// we need to set lazy values for the children
lazy[node<<1] = !lazy[node<<1];
lazy[(node<<1)+1] = !lazy[(node<<1)+1];
}
}
// At this point we are sure that pending lazy updates
// are done for current node. So we can return value
// If this segment lies in range
if (qs<=st && en<=qe)
return tree[node];
// If a part of this segment overlaps with the given range
int mid = (st+en)/2;
return countQuery((node<<1), st, mid, qs, qe) +
countQuery((node<<1)+1, mid+1, en, qs, qe);
}
// Driver program to run the case
int main()
{
int n = 5;
toggle(1, 0, n-1, 1, 2); //  Toggle 1 2
toggle(1, 0, n-1, 2, 4); //  Toggle 2 4
cout << countQuery(1, 0, n-1, 2, 3) << endl; //  Count 2 3
toggle(1, 0, n-1, 2, 4); //  Toggle 2 4
cout << countQuery(1, 0, n-1, 1, 4) << endl; //  Count 1 4
return 0;
}


JAVA

// Java program to implement toggle and
// count queries on a binary array.
class GFG
{
static final int MAX = 100000 ;
// segment tree to store count
// of 1's within range
static int tree[] = new int [MAX];
// bool type tree to collect the updates
// for toggling the values of 1 and 0 in
// given range
static boolean lazy[] = new boolean [MAX];
// function for collecting updates of toggling
// node --> index of current node in segment tree
// st --> starting index of current node
// en --> ending index of current node
// us --> starting index of range update query
// ue --> ending index of range update query
static void toggle( int node, int st,
int en, int us, int ue)
{
// If lazy value is non-zero for current
// node of segment tree, then there are
// some pending updates. So we need
// to make sure that the pending updates
// are done before making new updates.
// Because this value may be used by
// parent after recursive calls (See last
// line of this function)
if (lazy[node])
{
// Make pending updates using value
// stored in lazy nodes
lazy[node] = false ;
tree[node] = en - st + 1 - tree[node];
// checking if it is not leaf node
// because if it is leaf node then
// we cannot go further
if (st < en)
{
// We can postpone updating children
// we don't need their new values now.
// Since we are not yet updating children
// of 'node', we need to set lazy flags
// for the children
lazy[node << 1 ] = !lazy[node << 1 ];
lazy[ 1 + (node << 1 )] = !lazy[ 1 + (node << 1 )];
}
}
// out of range
if (st > en || us > en || ue < st)
{
return ;
}
// Current segment is fully in range
if (us <= st && en <= ue)
{
// Add the difference to current node
tree[node] = en - st + 1 - tree[node];
// same logic for checking leaf node or not
if (st < en)
{
// This is where we store values in lazy nodes,
// rather than updating the segment tree itelf
// Since we don't need these updated values now
// we postpone updates by storing values in lazy[]
lazy[node << 1 ] = !lazy[node << 1 ];
lazy[ 1 + (node << 1 )] = !lazy[ 1 + (node << 1 )];
}
return ;
}
// If not completely in rang,
// but overlaps, recur for children,
int mid = (st + en) / 2 ;
toggle((node << 1 ), st, mid, us, ue);
toggle((node << 1 ) + 1 , mid + 1 , en, us, ue);
// And use the result of children
// calls to update this node
if (st < en)
{
tree[node] = tree[node << 1 ] +
tree[(node << 1 ) + 1 ];
}
}
/* node --> Index of current node in the segment tree.
Initially 0 is passed as root is always at'
index 0
st & en --> Starting and ending indexes of the
segment represented by current node,
i.e., tree[node]
qs & qe --> Starting and ending indexes of query
range */
// function to count number of 1's
// within given range
static int countQuery( int node, int st,
int en, int qs, int qe)
{
// current node is out of range
if (st > en || qs > en || qe < st)
{
return 0 ;
}
// If lazy flag is set for current
// node of segment tree, then there
// are some pending updates. So we
// need to make sure that the pending
// updates are done before processing
// the sub sum query
if (lazy[node])
{
// Make pending updates to this node.
// Note that this node represents sum
// of elements in arr[st..en] and
// all these elements must be increased
// by lazy[node]
lazy[node] = false ;
tree[node] = en - st + 1 - tree[node];
// checking if it is not leaf node because if
// it is leaf node then we cannot go further
if (st < en)
{
// Since we are not yet updating children os si,
// we need to set lazy values for the children
lazy[node << 1 ] = !lazy[node << 1 ];
lazy[(node << 1 ) + 1 ] = !lazy[(node << 1 ) + 1 ];
}
}
// At this point we are sure that pending
// lazy updates are done for current node.
// So we can return value If this segment
// lies in range
if (qs <= st && en <= qe)
{
return tree[node];
}
// If a part of this segment overlaps
// with the given range
int mid = (st + en) / 2 ;
return countQuery((node << 1 ), st, mid, qs, qe) +
countQuery((node << 1 ) + 1 , mid + 1 , en, qs, qe);
}
// Driver Code
public static void main(String args[])
{
int n = 5 ;
toggle( 1 , 0 , n - 1 , 1 , 2 ); // Toggle 1 2
toggle( 1 , 0 , n - 1 , 2 , 4 ); // Toggle 2 4
System.out.println(countQuery( 1 , 0 , n - 1 , 2 , 3 )); // Count 2 3
toggle( 1 , 0 , n - 1 , 2 , 4 ); // Toggle 2 4
System.out.println(countQuery( 1 , 0 , n - 1 , 1 , 4 )); // Count 1 4
}
}
// This code is contributed by 29AjayKumar


Python3

# Python program to implement toggle and count
# queries on a binary array.
MAX = 100000
# segment tree to store count of 1's within range
tree = [ 0 ] * MAX
# bool type tree to collect the updates for toggling
# the values of 1 and 0 in given range
lazy = [ False ] * MAX
# function for collecting updates of toggling
# node --> index of current node in segment tree
# st --> starting index of current node
# en --> ending index of current node
# us --> starting index of range update query
# ue --> ending index of range update query
def toggle(node: int , st: int , en: int , us: int , ue: int ):
# If lazy value is non-zero for current node of segment
# tree, then there are some pending updates. So we need
# to make sure that the pending updates are done before
# making new updates. Because this value may be used by
# parent after recursive calls (See last line of this
# function)
if lazy[node]:
# Make pending updates using value stored in lazy nodes
lazy[node] = False
tree[node] = en - st + 1 - tree[node]
# checking if it is not leaf node because if
# it is leaf node then we cannot go further
if st < en:
# We can postpone updating children we don't
# need their new values now.
# Since we are not yet updating children of 'node',
# we need to set lazy flags for the children
lazy[node << 1 ] = not lazy[node << 1 ]
lazy[ 1 + (node << 1 )] = not lazy[ 1 + (node << 1 )]
# out of range
if st > en or us > en or ue < st:
return
# Current segment is fully in range
if us < = st and en < = ue:
# Add the difference to current node
tree[node] = en - st + 1 - tree[node]
# same logic for checking leaf node or not
if st < en:
# This is where we store values in lazy nodes,
# rather than updating the segment tree itelf
# Since we don't need these updated values now
# we postpone updates by storing values in lazy[]
lazy[node << 1 ] = not lazy[node << 1 ]
lazy[ 1 + (node << 1 )] = not lazy[ 1 + (node << 1 )]
return
# If not completely in rang, but overlaps, recur for
# children,
mid = (st + en) / / 2
toggle((node << 1 ), st, mid, us, ue)
toggle((node << 1 ) + 1 , mid + 1 , en, us, ue)
# And use the result of children calls to update this node
if st < en:
tree[node] = tree[node << 1 ] + tree[(node << 1 ) + 1 ]
# node --> Index of current node in the segment tree.
#         Initially 0 is passed as root is always at'
#         index 0
# st & en --> Starting and ending indexes of the
#             segment represented by current node,
#             i.e., tree[node]
# qs & qe --> Starting and ending indexes of query
#             range
# function to count number of 1's within given range
def countQuery(node: int , st: int , en: int , qs: int , qe: int ) - > int :
# current node is out of range
if st > en or qs > en or qe < st:
return 0
# If lazy flag is set for current node of segment tree,
# then there are some pending updates. So we need to
# make sure that the pending updates are done before
# processing the sub sum query
if lazy[node]:
# Make pending updates to this node. Note that this
# node represents sum of elements in arr[st..en] and
# all these elements must be increased by lazy[node]
lazy[node] = False
tree[node] = en - st + 1 - tree[node]
# checking if it is not leaf node because if
# it is leaf node then we cannot go further
if st < en:
# Since we are not yet updating children os si,
# we need to set lazy values for the children
lazy[node << 1 ] = not lazy[node << 1 ]
lazy[(node << 1 ) + 1 ] = not lazy[(node << 1 ) + 1 ]
# At this point we are sure that pending lazy updates
# are done for current node. So we can return value
# If this segment lies in range
if qs < = st and en < = qe:
return tree[node]
# If a part of this segment overlaps with the given range
mid = (st + en) / / 2
return countQuery((node << 1 ), st, mid, qs, qe) + countQuery(
(node << 1 ) + 1 , mid + 1 , en, qs, qe)
# Driver Code
if __name__ = = "__main__" :
n = 5
toggle( 1 , 0 , n - 1 , 1 , 2 ) # Toggle 1 2
toggle( 1 , 0 , n - 1 , 2 , 4 ) # Toggle 2 4
print (countQuery( 1 , 0 , n - 1 , 2 , 3 )) # count 2 3
toggle( 1 , 0 , n - 1 , 2 , 4 ) # Toggle 2 4
print (countQuery( 1 , 0 , n - 1 , 1 , 4 )) # count 1 4
# This code is contributed by
# sanjeev2552


C#

// C# program to implement toggle and
// count queries on a binary array.
using System;
public class GFG{
static readonly int MAX = 100000;
// segment tree to store count
// of 1's within range
static int []tree = new int [MAX];
// bool type tree to collect the updates
// for toggling the values of 1 and 0 in
// given range
static bool []lazy = new bool [MAX];
// function for collecting updates of toggling
// node --> index of current node in segment tree
// st --> starting index of current node
// en --> ending index of current node
// us --> starting index of range update query
// ue --> ending index of range update query
static void toggle( int node, int st,
int en, int us, int ue)
{
// If lazy value is non-zero for current
// node of segment tree, then there are
// some pending updates. So we need
// to make sure that the pending updates
// are done before making new updates.
// Because this value may be used by
// parent after recursive calls (See last
// line of this function)
if (lazy[node])
{
// Make pending updates using value
// stored in lazy nodes
lazy[node] = false ;
tree[node] = en - st + 1 - tree[node];
// checking if it is not leaf node
// because if it is leaf node then
// we cannot go further
if (st < en)
{
// We can postpone updating children
// we don't need their new values now.
// Since we are not yet updating children
// of 'node', we need to set lazy flags
// for the children
lazy[node << 1] = !lazy[node << 1];
lazy[1 + (node << 1)] = !lazy[1 + (node << 1)];
}
}
// out of range
if (st > en || us > en || ue < st)
{
return ;
}
// Current segment is fully in range
if (us <= st && en <= ue)
{
// Add the difference to current node
tree[node] = en - st + 1 - tree[node];
// same logic for checking leaf node or not
if (st < en)
{
// This is where we store values in lazy nodes,
// rather than updating the segment tree itelf
// Since we don't need these updated values now
// we postpone updates by storing values in lazy[]
lazy[node << 1] = !lazy[node << 1];
lazy[1 + (node << 1)] = !lazy[1 + (node << 1)];
}
return ;
}
// If not completely in rang,
// but overlaps, recur for children,
int mid = (st + en) / 2;
toggle((node << 1), st, mid, us, ue);
toggle((node << 1) + 1, mid + 1, en, us, ue);
// And use the result of children
// calls to update this node
if (st < en)
{
tree[node] = tree[node << 1] +
tree[(node << 1) + 1];
}
}
/* node --> Index of current node in the segment tree.
Initially 0 is passed as root is always at'
index 0
st & en --> Starting and ending indexes of the
segment represented by current node,
i.e., tree[node]
qs & qe --> Starting and ending indexes of query
range */
// function to count number of 1's
// within given range
static int countQuery( int node, int st,
int en, int qs, int qe)
{
// current node is out of range
if (st > en || qs > en || qe < st)
{
return 0;
}
// If lazy flag is set for current
// node of segment tree, then there
// are some pending updates. So we
// need to make sure that the pending
// updates are done before processing
// the sub sum query
if (lazy[node])
{
// Make pending updates to this node.
// Note that this node represents sum
// of elements in arr[st..en] and
// all these elements must be increased
// by lazy[node]
lazy[node] = false ;
tree[node] = en - st + 1 - tree[node];
// checking if it is not leaf node because if
// it is leaf node then we cannot go further
if (st < en)
{
// Since we are not yet updating children os si,
// we need to set lazy values for the children
lazy[node << 1] = !lazy[node << 1];
lazy[(node << 1) + 1] = !lazy[(node << 1) + 1];
}
}
// At this point we are sure that pending
// lazy updates are done for current node.
// So we can return value If this segment
// lies in range
if (qs <= st && en <= qe)
{
return tree[node];
}
// If a part of this segment overlaps
// with the given range
int mid = (st + en) / 2;
return countQuery((node << 1), st, mid, qs, qe) +
countQuery((node << 1) + 1, mid + 1, en, qs, qe);
}
// Driver Code
public static void Main()
{
int n = 5;
toggle(1, 0, n - 1, 1, 2); // Toggle 1 2
toggle(1, 0, n - 1, 2, 4); // Toggle 2 4
Console.WriteLine(countQuery(1, 0, n - 1, 2, 3)); // Count 2 3
toggle(1, 0, n - 1, 2, 4); // Toggle 2 4
Console.WriteLine(countQuery(1, 0, n - 1, 1, 4)); // Count 1 4
}
}
/*This code is contributed by PrinciRaj1992*/


Javascript

<script>
// JavaScript program to implement toggle and
// count queries on a binary array.
let MAX = 100000;
// segment tree to store count
// of 1's within range
let tree= new Array(MAX);
// bool type tree to collect the updates
// for toggling the values of 1 and 0 in
// given range
let lazy = new Array(MAX);
for (let i=0;i<MAX;i++)
{
tree[i]=0;
lazy[i]= false ;
}
// function for collecting updates of toggling
// node --> index of current node in segment tree
// st --> starting index of current node
// en --> ending index of current node
// us --> starting index of range update query
// ue --> ending index of range update query
function toggle(node,st,en,us,ue)
{
// If lazy value is non-zero for current
// node of segment tree, then there are
// some pending updates. So we need
// to make sure that the pending updates
// are done before making new updates.
// Because this value may be used by
// parent after recursive calls (See last
// line of this function)
if (lazy[node])
{
// Make pending updates using value
// stored in lazy nodes
lazy[node] = false ;
tree[node] = en - st + 1 - tree[node];
// checking if it is not leaf node
// because if it is leaf node then
// we cannot go further
if (st < en)
{
// We can postpone updating children
// we don't need their new values now.
// Since we are not yet updating children
// of 'node', we need to set lazy flags
// for the children
lazy[node << 1] = !lazy[node << 1];
lazy[1 + (node << 1)] = !lazy[1 + (node << 1)];
}
}
// out of range
if (st > en || us > en || ue < st)
{
return ;
}
// Current segment is fully in range
if (us <= st && en <= ue)
{
// Add the difference to current node
tree[node] = en - st + 1 - tree[node];
// same logic for checking leaf node or not
if (st < en)
{
// This is where we store values in lazy nodes,
// rather than updating the segment tree itelf
// Since we don't need these updated values now
// we postpone updates by storing values in lazy[]
lazy[node << 1] = !lazy[node << 1];
lazy[1 + (node << 1)] = !lazy[1 + (node << 1)];
}
return ;
}
// If not completely in rang,
// but overlaps, recur for children,
let mid = Math.floor((st + en) / 2);
toggle((node << 1), st, mid, us, ue);
toggle((node << 1) + 1, mid + 1, en, us, ue);
// And use the result of children
// calls to update this node
if (st < en)
{
tree[node] = tree[node << 1] +
tree[(node << 1) + 1];
}
}
/* node --> Index of current node in the segment tree.
Initially 0 is passed as root is always at'
index 0
st & en --> Starting and ending indexes of the
segment represented by current node,
i.e., tree[node]
qs & qe --> Starting and ending indexes of query
range */
// function to count number of 1's
// within given range
function countQuery(node,st,en,qs,qe)
{
// current node is out of range
if (st > en || qs > en || qe < st)
{
return 0;
}
// If lazy flag is set for current
// node of segment tree, then there
// are some pending updates. So we
// need to make sure that the pending
// updates are done before processing
// the sub sum query
if (lazy[node])
{
// Make pending updates to this node.
// Note that this node represents sum
// of elements in arr[st..en] and
// all these elements must be increased
// by lazy[node]
lazy[node] = false ;
tree[node] = en - st + 1 - tree[node];
// checking if it is not leaf node because if
// it is leaf node then we cannot go further
if (st < en)
{
// Since we are not yet updating children os si,
// we need to set lazy values for the children
lazy[node << 1] = !lazy[node << 1];
lazy[(node << 1) + 1] = !lazy[(node << 1) + 1];
}
}
// At this point we are sure that pending
// lazy updates are done for current node.
// So we can return value If this segment
// lies in range
if (qs <= st && en <= qe)
{
return tree[node];
}
// If a part of this segment overlaps
// with the given range
let mid = Math.floor((st + en) / 2);
return countQuery((node << 1), st, mid, qs, qe) +
countQuery((node << 1) + 1, mid + 1, en, qs, qe);
}
// Driver Code
let n = 5;
toggle(1, 0, n - 1, 1, 2); // Toggle 1 2
toggle(1, 0, n - 1, 2, 4); // Toggle 2 4
document.write(countQuery(1, 0, n - 1, 2, 3)+ "<br>" ); // Count 2 3
toggle(1, 0, n - 1, 2, 4); // Toggle 2 4
document.write(countQuery(1, 0, n - 1, 1, 4)+ "<br>" ); // Count 1 4
// This code is contributed by rag2127
</script>


输出:

12

本文由 沙申克·米什拉(古卢) .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 写极客。组织 或者把你的文章寄去评论-team@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享