给定一个由N个正整数组成的数组arr []和一个{a,K,X}类型的2D数组query [] [] ,使得如果a的值为1 ,则将前K个数组元素乘以X。否则,将最后K个数组元素乘以X。任务是在对原始阵列执行每次查询之后,计算阵列的GCD。
例子:
Input: arr[] = {2, 3, 4, 8}, Queries[][3] = {{1, 2, 2}, {2, 4, 5}}
Output: 2 5
Explanation:
Query 1: The given query is {1, 2, 2}. After multiplying the first 2 array elements by 2, arr[] modifies to {4, 6, 4, 8}. GCD of the modified array is 2.
Query 2: The given query is {2, 4, 5}. After multiplying the last 4 elements array elements by 5, arr[] modifies to {10, 15, 20, 40}. GCD of the updated array is 5.
Input: arr[] = {4, 12, 4, 9}, Queries[][3] = {{1, 3, 3}, {2, 4, 1}}
Output: 3 1
天真的方法:最简单的方法是通过执行每个查询来更新给定的数组,然后找到更新后的数组的GCD。
时间复杂度: O(N * Q * log(M)),其中M是数组中存在的最大元素。
辅助空间: O(N)
高效的方法:可以通过存储给定数组的前缀和后缀GCD数组并按照以下步骤在O(1)时间内解决每个查询来优化上述方法:
- 初始化大小为N的数组prefix []和后缀[] ,以存储给定数组的前缀和后缀GCD数组。
- 从正面和背面遍历数组,并在每个索引处找到前缀和后缀GCD,并将其分别存储在prefix []和suffix []中。
- 现在,遍历数组query [] ,并对每个查询{a,K,X}执行以下操作:
- 如果K的值为N,则打印前缀[N – 1] * X的结果。
- 如果a的值为1,则找到前缀[K – 1] * X和后缀[K]的GCD作为结果,因为前缀[K – 1] * X是前K个数字和后缀[ ]的新GCD。 K + 1]是其余数组元素的GCD。
- 如果a的值为2,则找到前缀[N – K – 1]的GCD和后缀[N – K] * X作为结果,因为前缀[N – K – 1] * X是的新GCD。前K个数字和后缀[N – K]是其余数组元素的GCD。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the GCD after performing
// each query on array elements
void findGCDQueries(int arr[], int N,
int Queries[][3],
int Q)
{
// Stores prefix array and suffix
// array
int prefix[N], suffix[N];
prefix[0] = arr[0];
suffix[N - 1] = arr[N - 1];
// Build prefix array
for (int i = 1; i < N; i++) {
prefix[i] = __gcd(prefix[i - 1],
arr[i]);
}
// Build suffix array
for (int i = N - 2; i >= 0; i--) {
suffix[i] = __gcd(suffix[i + 1],
arr[i]);
}
// Traverse queries array
for (int i = 0; i < Q; i++) {
int a = Queries[i][0];
int K = Queries[i][1];
int X = Queries[i][2];
// Edge Case when update is
// is required till the end
if (K == N) {
cout << prefix[N - 1] * X;
continue;
}
// Edge Case when update is
// is required till the front
if (a == 1) {
cout << __gcd(prefix[K - 1] * X,
suffix[K]);
}
// Find the resultant operation
// for each query
else {
cout << __gcd(suffix[N - K] * X,
prefix[N - K - 1]);
}
cout << " ";
}
}
// Driver Code
int main()
{
int arr[] = { 2, 3, 4, 8 };
int N = sizeof(arr) / sizeof(arr[0]);
int Queries[][3] = {
{ 1, 2, 2 },
{ 2, 4, 5 }
};
int Q = sizeof(Queries)
/ sizeof(Queries[0]);
findGCDQueries(arr, N, Queries, Q);
return 0;
}
Java
// Java program to implement
// the above approach
import java.io.*;
import java.util.*;
class GFG
{
// Recursive function to return gcd of a and b
static int gcd(int a, int b)
{
// Everything divides 0
if (a == 0)
return b;
if (b == 0)
return a;
// base case
if (a == b)
return a;
// a is greater
if (a > b)
return gcd(a - b, b);
return gcd(a, b - a);
}
// Function to find the GCD after performing
// each query on array elements
static void findGCDQueries(int arr[], int N,
int Queries[][],
int Q)
{
// Stores prefix array and suffix
// array
int prefix[] = new int[N], suffix[] = new int[N];
prefix[0] = arr[0];
suffix[N - 1] = arr[N - 1];
// Build prefix array
for (int i = 1; i < N; i++) {
prefix[i] = gcd(prefix[i - 1],
arr[i]);
}
// Build suffix array
for (int i = N - 2; i >= 0; i--) {
suffix[i] = gcd(suffix[i + 1],
arr[i]);
}
// Traverse queries array
for (int i = 0; i < Q; i++) {
int a = Queries[i][0];
int K = Queries[i][1];
int X = Queries[i][2];
// Edge Case when update is
// is required till the end
if (K == N) {
System.out.print(prefix[N - 1] * X);
continue;
}
// Edge Case when update is
// is required till the front
if (a == 1) {
System.out.print(gcd(prefix[K - 1] * X,
suffix[K]));
}
// Find the resultant operation
// for each query
else {
System.out.print(gcd(suffix[N - K] * X,
prefix[N - K - 1]));
}
System.out.print(" ");
}
}
// Driver Code
public static void main(String[] args)
{
int arr[] = { 2, 3, 4, 8 };
int N = arr.length;
int Queries[][] = {
{ 1, 2, 2 },
{ 2, 4, 5 }
};
int Q = Queries.length;
findGCDQueries(arr, N, Queries, Q);
}
}
// This code is cntributed by sanjoy_62.
Python3
# Python 3 program for the above approach
from math import gcd
# Function to find the GCD after performing
# each query on array elements
def findGCDQueries(arr, N, Queries, Q):
# Stores prefix array and suffix
# array
prefix = [0 for i in range(N)]
suffix = [0 for i in range(N)]
prefix[0] = arr[0]
suffix[N - 1] = arr[N - 1]
# Build prefix array
for i in range(1,N,1):
prefix[i] = gcd(prefix[i - 1], arr[i])
# Build suffix array
i = N - 2
while(i>= 0):
suffix[i] = gcd(suffix[i + 1], arr[i])
i -= 1
# Traverse queries array
for i in range(Q):
a = Queries[i][0]
K = Queries[i][1]
X = Queries[i][2]
# Edge Case when update is
# is required till the end
if (K == N):
print(prefix[N - 1] * X,end = " ")
continue
# Edge Case when update is
# is required till the front
if (a == 1):
print(gcd(prefix[K - 1] * X,suffix[K]),end = " ")
# Find the resultant operation
# for each query
else:
print(gcd(suffix[N - K] * X, prefix[N - K - 1]),end = " ")
# Driver Code
if __name__ == '__main__':
arr = [2, 3, 4, 8]
N = len(arr)
Queries = [[1, 2, 2], [2, 4, 5]]
Q = len(Queries)
findGCDQueries(arr, N, Queries, Q)
# This code is contributed by SURENDRA_GANGWAR.
C#
// C# program to implement
// the above approach
using System;
public class GFG
{
// Recursive function to return gcd of a and b
static int gcd(int a, int b)
{
// Everything divides 0
if (a == 0)
return b;
if (b == 0)
return a;
// base case
if (a == b)
return a;
// a is greater
if (a > b)
return gcd(a - b, b);
return gcd(a, b - a);
}
// Function to find the GCD after performing
// each query on array elements
static void findGCDQueries(int []arr, int N,
int [,]Queries,
int Q)
{
// Stores prefix array and suffix
// array
int []prefix = new int[N];
int []suffix = new int[N];
prefix[0] = arr[0];
suffix[N - 1] = arr[N - 1];
// Build prefix array
for (int i = 1; i < N; i++) {
prefix[i] = gcd(prefix[i - 1],
arr[i]);
}
// Build suffix array
for (int i = N - 2; i >= 0; i--) {
suffix[i] = gcd(suffix[i + 1],
arr[i]);
}
// Traverse queries array
for (int i = 0; i < Q; i++) {
int a = Queries[i,0];
int K = Queries[i,1];
int X = Queries[i,2];
// Edge Case when update is
// is required till the end
if (K == N) {
Console.Write(prefix[N - 1] * X);
continue;
}
// Edge Case when update is
// is required till the front
if (a == 1) {
Console.Write(gcd(prefix[K - 1] * X,
suffix[K]));
}
// Find the resultant operation
// for each query
else {
Console.Write(gcd(suffix[N - K] * X,
prefix[N - K - 1]));
}
Console.Write(" ");
}
}
// Driver Code
public static void Main(string[] args)
{
int []arr = { 2, 3, 4, 8 };
int N = arr.Length;
int [,]Queries = {
{ 1, 2, 2 },
{ 2, 4, 5 }
};
int Q = Queries.GetLength(0);
findGCDQueries(arr, N, Queries, Q);
}
}
// This code is cntributed by AnkThon.
2 5
时间复杂度: O((N + Q)* log M),其中M是数组的最大元素。
辅助空间: O(N)