Javascript程序在K循环移位后将给定数组分成两半后使用按位或查找数组和
给定一个长度为N的数组 A[] ,其中 N 是偶数,任务是回答Q个独立查询,其中每个查询由一个正整数K组成,表示对数组执行的循环移位的次数,并找到元素的总和通过对分割后的数组执行按位或运算。
注意:每个查询都从原始数组开始。
例子:
Input: A[] = {12, 23, 4, 21, 22, 76}, Q = 1, K = 2
Output: 117
Explanation:
Since K is 2, modified array A[]={22, 76, 12, 23, 4, 21}.
Bitwise OR of first half of array = (22 | 76 | 12) = 94
Bitwise OR of second half of array = (21 | 23 | 4) = 23
Sum of OR values is 94 + 23 = 117
Input: A[] = {7, 44, 19, 86, 65, 39, 75, 101}, Q = 1, K = 4
Output: 238
Since K is 4, modified array A[]={65, 39, 75, 101, 7, 44, 19, 86}.
Bitwise OR of first half of array = 111
Bitwise OR of second half of array = 127
Sum of OR values is 111 + 127 = 238
天真的方法:
要解决上面提到的问题,最简单的方法是将数组的每个元素移动K % (N / 2) ,然后遍历数组来计算每个查询的两半的 OR。但是这种方法效率不高,因此可以进一步优化。
有效的方法:
为了优化上述方法,我们可以借助 Segment Tree 数据结构。
Observation:
- We can observe that after exactly N / 2 right circular shifts the two halves of the array become the same as in the original array. This effectively reduces the number of rotations to K % (N / 2).
- Performing a right circular shift is basically shifting the last element of the array to the front. So for any positive integer X performing X right circular shifts is equal to shifting the last X elements of the array to the front.
以下是解决问题的步骤:
- 为原始数组A[]构造一个段树并分配一个变量,比如说i = K % (N / 2) 。
- 然后对于每个查询,我们使用查找按位或的段树;即从末尾开始的 i 个元素的按位或或第一个(N / 2) – i – 1 个元素的按位或。
- 然后计算[(N / 2) – i, N – i – 1]范围内元素的按位或。
- 将这两个结果相加以获得第 i 个查询的答案。
下面是上述方法的实现:
Javascript
238
230
时间复杂度: O(N + Q*logN)
辅助空间: O(4*MAX)
有关详细信息,请参阅完整的文章在 K 循环移位后将给定数组分成两半后使用按位或查找数组和!