给定一个由N 个元素和Q 个查询组成的数组arr[] ,由L 、 R和K 表示。任务是在与 K 进行按位异或之后打印子数组[L, R] 中奇偶校验元素的计数。
例子:
Input: arr[] = {5, 2, 3, 1, 4, 8, 10}
query[] = {{0, 5, 3}, {1, 4, 8}, {4, 6, 10}}
Output:
4 2
1 3
2 1
Explanation:
In query 1, the odd and even parity elements in subarray [0:5] are [2, 1, 4, 8] and [5, 3]. Now after XOR with K = 3, the number of odd and even parity elements are 4 and 2 respectively.
In query 2, the odd and even parity elements in subarray [1:4] are [2, 1, 4] and [3]. Now after XOR with K = 8, the number of odd and even parity elements are 1 and 3 respectively.
In query 3, the odd and even parity elements in subarray [4:6] are [4, 8] and [10]. Now after XOR with K = 10, the number of odd and even parity elements are 2 and 1 respectively.
方法:思想是使用MO的算法对所有查询进行预处理,以便一个查询的结果可以在下一个查询中使用。
- 对所有查询进行排序,将 L 值从0 到 √n – 1的查询放在一起,然后是从√n 到 2 ×√n – 1 的查询,依此类推。块内的所有查询都按 R 值的升序排序。
- 计算奇校验元素,然后计算偶校验元素为
- 奇偶校验元素异或后的观察:
- 两个奇校验元素的异或是一个偶校验元素。
- 两个偶校验元素的异或是一个偶校验元素。
- 一个偶校验元素和另一个奇校验元素的异或是奇校验元素,反之亦然。
- 一一处理所有查询并增加奇校验元素的数量,现在我们将检查 K 的奇偶校验。如果K具有偶校验,然后奇和偶校验的计数保持我们交换他们同其他人。
- 让count_oddP存储先前查询中奇数奇偶校验元素的计数。
- 删除先前查询的额外元素并为当前查询添加新元素。例如,如果之前的查询是 [0, 8] 而当前的查询是 [3, 9],那么移除元素 arr[0]、arr[1] 和 arr[2] 并添加 arr[9]。
- 为了显示结果,请按照提供的顺序对查询进行排序。
添加元素
- 如果当前元素具有奇校验,则增加奇校验的计数。
删除元素
- 如果当前元素具有奇校验,则减少奇校验的计数。
下面是上述方法的实现:
C++
// C++ program to count odd and
// even parity elements in subarray
// after XOR with K
#include
using namespace std;
#define MAX 100000
// Variable to represent block size.
// This is made global so compare()
// of sort can use it
int block;
// Structure to represent
// a query range
struct Query {
// Starting index
int L, R, K, index;
// Count of odd
// parity elements
int odd;
// Count of even
// parity elements
int even;
};
// To store the count of
// odd parity elements
int count_oddP;
// Function used to sort all queries so that
// all queries of the same block are arranged
// together and within a block, queries are
// sorted in increasing order of R values.
bool compare(Query x, Query y)
{
// Different blocks, sort by block.
if (x.L / block != y.L / block)
return x.L / block < y.L / block;
// Same block, sort by R value
return x.R < y.R;
}
// Function used to sort all queries
// in order of their index value so
// that results of queries can be
// printed in same order as of input
bool compare1(Query x, Query y)
{
return x.index < y.index;
}
// Function to Add elements
// of current range
void add(int currL, int a[])
{
// _builtin_parity(x)returns true(1)
// if the number has odd parity else
// it returns false(0) for even parity.
if (__builtin_parity(a[currL]))
count_oddP++;
}
// Function to remove elements
// of previous range
void remove(int currR, int a[])
{
// _builtin_parity(x)returns true(1)
// if the number has odd parity else
// it returns false(0) for even parity.
if (__builtin_parity(a[currR]))
count_oddP--;
}
// Function to generate the result of queries
void queryResults(int a[], int n, Query q[],
int m)
{
// Initialize number of odd parity
// elements to 0
count_oddP = 0;
// Find block size
block = (int)sqrt(n);
// Sort all queries so that queries of
// same blocks are arranged together.
sort(q, q + m, compare);
// Initialize current L, current R and
// current result
int currL = 0, currR = 0;
for (int i = 0; i < m; i++) {
// L and R values of current range
int L = q[i].L,
R = q[i].R,
k = q[i].K;
// Add Elements of current range
while (currR <= R) {
add(currR, a);
currR++;
}
while (currL > L) {
add(currL - 1, a);
currL--;
}
// Remove element of previous range
while (currR > R + 1)
{
remove(currR - 1, a);
currR--;
}
while (currL < L) {
remove(currL, a);
currL++;
}
// If parity of K is even
// then the count of odd
// and even parity remains
// the same
if (!__builtin_parity(k)) {
q[i].odd = count_oddP;
q[i].even
= R - L + 1 - count_oddP;
}
// If parity of K is odd
// we swap the count of
// odd and even parity
// elements
else {
q[i].odd
= R - L + 1 - count_oddP;
q[i].even = count_oddP;
}
}
}
// Function to display the results of
// queries in their initial order
void printResults(Query q[], int m)
{
sort(q, q + m, compare1);
for (int i = 0; i < m; i++) {
cout << q[i].odd << " "
<< q[i].even << endl;
}
}
// Driver Code
int main()
{
int arr[] = { 5, 2, 3, 1, 4, 8, 10 };
int n = sizeof(arr) / sizeof(arr[0]);
Query q[] = { { 0, 5, 3, 0, 0, 0 },
{ 1, 4, 8, 1, 0, 0 },
{ 4, 6, 10, 2, 0, 0 } };
int m = sizeof(q) / sizeof(q[0]);
queryResults(arr, n, q, m);
printResults(q, m);
return 0;
}
Java
// Java program to count odd and
// even parity elements in subarray
// after XOR with K
import java.io.*;
import java.util.*;
// Class to represent
// a query range
class Query
{
int L, R, K, index;
// Count of odd
// parity elements
int odd;
// Count of even
// parity elements
int even;
Query(int L, int R, int K,
int index, int odd, int even)
{
this.L = L;
this.R = R;
this.K = K;
this.index = index;
this.odd = odd;
this.even = even;
}
}
class GFG{
// Variable to represent block size.
static int block;
// To store the count of
// odd parity elements
static int count_oddP;
// Function to Add elements
// of current range
static void add(int currL, int a[])
{
// _builtin_parity(x)returns true
// if the number has odd parity else
// it returns false for even parity.
if (__builtin_parity(a[currL]))
count_oddP++;
}
// Function to remove elements
// of previous range
static void remove(int currR, int a[])
{
// _builtin_parity(x)returns true
// if the number has odd parity else
// it returns false for even parity.
if (__builtin_parity(a[currR]))
count_oddP--;
}
// Function to generate the result of queries
static void queryResults(int a[], int n, Query q[],
int m)
{
// Initialize number of odd parity
// elements to 0
count_oddP = 0;
// Find block size
block = (int)(Math.sqrt(n));
// sort all queries so that all queries
// of the same block are arranged together
// and within a block, queries are sorted
// in increasing order of R values.
Arrays.sort(q, (Query x, Query y) ->
{
// Different blocks, sort by block.
if (x.L / block != y.L / block)
return x.L / block - y.L / block;
// Same block, sort by R value
return x.R - y.R;
});
// Initialize current L, current R and
// current result
int currL = 0, currR = 0;
for(int i = 0; i < m; i++)
{
// L and R values of current range
int L = q[i].L, R = q[i].R, k = q[i].K;
// Add Elements of current range
while (currR <= R)
{
add(currR, a);
currR++;
}
while (currL > L)
{
add(currL - 1, a);
currL--;
}
// Remove element of previous range
while (currR > R + 1)
{
remove(currR - 1, a);
currR--;
}
while (currL < L)
{
remove(currL, a);
currL++;
}
// If parity of K is even
// then the count of odd
// and even parity remains
// the same
if (!__builtin_parity(k))
{
q[i].odd = count_oddP;
q[i].even = R - L + 1 - count_oddP;
}
// If parity of K is odd
// we swap the count of
// odd and even parity
// elements
else
{
q[i].odd = R - L + 1 - count_oddP;
q[i].even = count_oddP;
}
}
}
static boolean __builtin_parity(int K)
{
return (Integer.bitCount(K) % 2) == 1;
}
// Function to display the results of
// queries in their initial order
static void printResults(Query q[], int m)
{
Arrays.sort(q, (Query x, Query y) ->
// sort all queries
// in order of their
// index value so that results
// of queries can be printed
// in same order as of input);
x.index - y.index);
for(int i = 0; i < m; i++)
{
System.out.println(q[i].odd + " " +
q[i].even);
}
}
// Driver Code
public static void main(String[] args)
{
int arr[] = { 5, 2, 3, 1, 4, 8, 10 };
int n = arr.length;
Query q[] = new Query[3];
q[0] = new Query(0, 5, 3, 0, 0, 0);
q[1] = new Query(1, 4, 8, 1, 0, 0);
q[2] = new Query(4, 6, 10, 2, 0, 0);
int m = q.length;
queryResults(arr, n, q, m);
printResults(q, m);
}
}
// This code is contributed by jithin
4 2
1 3
2 1
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live