给定一个由N个整数和Q个查询组成的数组arr [] 。每个查询由3个整数L , R和K组成。您可以单步从索引i移至索引i + 1 ,也可以单步停留在该特定索引中。您可以从L的最大的k步移动到右食指和打印每次你在每一个步骤,包括第L号数的总和。任务是在最多K个动作中使总和最大化。如果我们不能以K步从L移到R ,则打印“ No” 。
例子:
Input: arr[] = {1, 3, 2, -4, -5}, q = {
{0, 2, 2},
{0, 2, 4},
{3, 4, 1},
{0, 4, 2}}
Output:
6
12
-9
No
For first query:
In first step move from 0th index to 1st index, hence 1 + 3 = 4
In second step move from 1st index to 2nd index, hence 4 + 2 = 6
For second query:
In first step move from 0th index to 1st index, hence 1 + 3 = 4
In second step stay at the 1st index, hence 4 + 3 = 7
In third step again stay at the 1st index, hence 7 + 3 = 10
In fourth step move from 1st index to 2nd index only, hence 10 + 2 = 12
一个幼稚的方法是首先检查L – R> K ,如果不是,则我们不能以K为步长从L移到R索引。从L迭代到R ,得到L和R之间所有元素的总和。然后找到L和R范围内的最大元素,答案将是(K –(R – L))* max范围内的元素之和。如果最大值为负数,我们将精确执行R – L动作,否则我们将在[L,R]范围内的最大数字索引处执行额外的步骤。
时间复杂度:每个查询为O(R – L)。
一种有效的方法是使用[L,R]范围内的分段树来找到最大数量,并使用前缀和来找到该范围内的和。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
// Function to create the tree
void tree(int low, int high, int pos,
int b[], int a[], int n)
{
// Leaf nodes
if (low == high) {
b[pos] = a[high];
return;
}
int mid = (high + low) / 2;
// Left subtree
tree(low, mid, 2 * pos + 1, b, a, n);
// Right subtree
tree(mid + 1, high, 2 * pos + 2, b, a, n);
// Merge the maximum
b[pos] = max(b[2 * pos + 1], b[2 * pos + 2]);
}
// Function that returns the maximum in range L and R
int rangemax(int s, int e, int low, int high,
int pos, int b[], int a[], int n)
{
// Complete overlap
if (low <= s && high >= e)
return b[pos];
// Out of range completely
if (e < low || s > high)
return INT_MIN;
int mid = (s + e) / 2;
// Find maximum in left and right subtrees
int left = rangemax(s, mid, low, high,
2 * pos + 1, b, a, n);
int right = rangemax(mid + 1, e, low, high,
2 * pos + 2, b, a, n);
// Return the maximum of both
return max(left, right);
}
// Function that solves a query
int solveQuery(int l, int r, int k, int n, int a[],
int b[], int prefix[])
{
// If there are ko
if (r - l > k)
return -1;
// Find maximum in range L and R
int maximum = rangemax(0, n - 1, l, r, 0, b, a, n);
// If maximum is 0
if (maximum < 0)
maximum = 0;
// Find the prefix sum
int rangesum = prefix[r];
// If not first element
if (l > 0)
rangesum -= prefix[l - 1];
// Get the answer
int answer = rangesum + (k - (r - l)) * maximum;
return answer;
}
// Function that solves the queries
void solveQueries(int n, int a[], int b[],
int prefix[], int queries[][3], int q)
{
// Solve all the queries
for (int i = 0; i < q; i++) {
int ans = solveQuery(queries[i][0], queries[i][1],
queries[i][2], n, a, b, prefix);
if (ans != -1)
cout << ans << endl;
else
cout << "No" << endl;
}
}
// Function to find the prefix sum
void findPrefixSum(int prefix[], int a[], int n)
{
prefix[0] = a[0];
for (int i = 1; i < n; i++) {
prefix[i] = prefix[i - 1] + a[i];
}
}
// Driver code
int main()
{
int a[] = { 1, 3, 2, -4, -5 };
int n = sizeof(a) / sizeof(a[0]);
// Array for segment tree
int b[5 * n];
// Create segment tree
tree(0, n - 1, 0, b, a, n);
int prefix[n];
// Fill prefix sum array
findPrefixSum(prefix, a, n);
// Queries
int queries[][3] = { { 0, 2, 2 },
{ 0, 2, 4 },
{ 3, 4, 1 },
{ 0, 4, 2 } };
int q = sizeof(queries) / sizeof(queries[0]);
solveQueries(n, a, b, prefix, queries, q);
return 0;
}
Java
// Java implementation of the approach
class GFG
{
// Function to create the tree
static void tree(int low, int high, int pos,
int b[], int a[], int n)
{
// Leaf nodes
if (low == high)
{
b[pos] = a[high];
return;
}
int mid = (high + low) / 2;
// Left subtree
tree(low, mid, 2 * pos + 1, b, a, n);
// Right subtree
tree(mid + 1, high, 2 * pos + 2, b, a, n);
// Merge the maximum
b[pos] = Math.max(b[2 * pos + 1], b[2 * pos + 2]);
}
// Function that returns the maximum in range L and R
static int rangemax(int s, int e, int low, int high,
int pos, int b[], int a[], int n)
{
// Complete overlap
if (low <= s && high >= e)
return b[pos];
// Out of range completely
if (e < low || s > high)
return Integer.MIN_VALUE;
int mid = (s + e) / 2;
// Find maximum in left and right subtrees
int left = rangemax(s, mid, low, high,
2 * pos + 1, b, a, n);
int right = rangemax(mid + 1, e, low, high,
2 * pos + 2, b, a, n);
// Return the maximum of both
return Math.max(left, right);
}
// Function that solves a query
static int solveQuery(int l, int r, int k, int n, int a[],
int b[], int prefix[])
{
// If there are ko
if (r - l > k)
return -1;
// Find maximum in range L and R
int maximum = rangemax(0, n - 1, l, r, 0, b, a, n);
// If maximum is 0
if (maximum < 0)
maximum = 0;
// Find the prefix sum
int rangesum = prefix[r];
// If not first element
if (l > 0)
rangesum -= prefix[l - 1];
// Get the answer
int answer = rangesum + (k - (r - l)) * maximum;
return answer;
}
// Function that solves the queries
static void solveQueries(int n, int a[], int b[],
int prefix[], int queries[][], int q)
{
// Solve all the queries
for (int i = 0; i < q; i++)
{
int ans = solveQuery(queries[i][0], queries[i][1],
queries[i][2], n, a, b, prefix);
if (ans != -1)
System.out.println(ans);
else
System.out.println("No" );
}
}
// Function to find the prefix sum
static void findPrefixSum(int prefix[], int a[], int n)
{
prefix[0] = a[0];
for (int i = 1; i < n; i++)
{
prefix[i] = prefix[i - 1] + a[i];
}
}
// Driver code
public static void main(String[] args)
{
int a[] = { 1, 3, 2, -4, -5 };
int n = a.length;
// Array for segment tree
int b[] = new int[5 * n];
// Create segment tree
tree(0, n - 1, 0, b, a, n);
int prefix[] = new int[n];
// Fill prefix sum array
findPrefixSum(prefix, a, n);
// Queries
int queries[][] = { { 0, 2, 2 },
{ 0, 2, 4 },
{ 3, 4, 1 },
{ 0, 4, 2 } };
int q = queries.length;
solveQueries(n, a, b, prefix, queries, q);
}
}
/* This code contributed by PrinciRaj1992 */
Python3
# Python3 implementation of the approach
# Function to create the tree
def tree( low, high, pos, b, a, n):
# Leaf nodes
if (low == high):
b[pos] = a[high]
return
mid = (high + low) // 2
# Left subtree
tree(low, mid, 2 * pos + 1, b, a, n)
# Right subtree
tree(mid + 1, high, 2 * pos + 2, b, a, n)
# Merge the maximum
b[pos] = max(b[2 * pos + 1], b[2 * pos + 2])
# Function that returns the maximum in range L and R
def rangemax(s, e, low, high, pos, b, a, n):
# Complete overlap
if (low <= s and high >= e):
return b[pos]
# Out of range completely
if (e < low or s > high):
return -(2**32)
mid = (s + e) // 2
# Find maximum in left and right subtrees
left = rangemax(s, mid, low, high, 2 * pos + 1, b, a, n)
right = rangemax(mid + 1, e, low, high, 2 * pos + 2, b, a, n)
# Return the maximum of both
return max(left, right)
# Function that solves a query
def solveQuery(l, r, k, n, a, b, prefix):
# If there are ko
if (r - l > k):
return -1
# Find maximum in range L and R
maximum = rangemax(0, n - 1, l, r, 0, b, a, n)
# If maximum is 0
if (maximum < 0):
maximum = 0
# Find the prefix sum
rangesum = prefix[r]
# If not first element
if (l > 0):
rangesum -= prefix[l - 1]
# Get the answer
answer = rangesum + (k - (r - l)) * maximum
return answer
# Function that solves the queries
def solveQueries( n, a, b, prefix, queries, q):
# Solve all the queries
for i in range(q):
ans = solveQuery(queries[i][0], queries[i][1],
queries[i][2], n, a, b, prefix)
if (ans != -1):
print(ans)
else:
print("No")
# Function to find the prefix sum
def findPrefixSum( prefix, a, n):
prefix[0] = a[0]
for i in range(1, n):
prefix[i] = prefix[i - 1] + a[i]
# Driver code
a = [1, 3, 2, -4, -5 ]
n = len(a)
# Array for segment tree
b = [0]*(5 * n)
# Create segment tree
tree(0, n - 1, 0, b, a, n)
prefix = [0]*n
# Fill prefix sum array
findPrefixSum(prefix, a, n)
# Queries
queries= [[0, 2, 2],[0, 2, 4],[3, 4, 1],[0, 4, 2]]
q = len(queries)
solveQueries(n, a, b, prefix, queries, q)
# This code is contributed by SHUBHAMSINGH10
C#
// C# program to implement
// the above approach
using System;
class GFG
{
// Function to create the tree
static void tree(int low, int high, int pos,
int []b, int []a, int n)
{
// Leaf nodes
if (low == high)
{
b[pos] = a[high];
return;
}
int mid = (high + low) / 2;
// Left subtree
tree(low, mid, 2 * pos + 1, b, a, n);
// Right subtree
tree(mid + 1, high, 2 * pos + 2, b, a, n);
// Merge the maximum
b[pos] = Math.Max(b[2 * pos + 1], b[2 * pos + 2]);
}
// Function that returns the maximum in range L and R
static int rangemax(int s, int e, int low, int high,
int pos, int []b, int []a, int n)
{
// Complete overlap
if (low <= s && high >= e)
return b[pos];
// Out of range completely
if (e < low || s > high)
return int.MinValue;
int mid = (s + e) / 2;
// Find maximum in left and right subtrees
int left = rangemax(s, mid, low, high,
2 * pos + 1, b, a, n);
int right = rangemax(mid + 1, e, low, high,
2 * pos + 2, b, a, n);
// Return the maximum of both
return Math.Max(left, right);
}
// Function that solves a query
static int solveQuery(int l, int r, int k, int n, int []a,
int []b, int []prefix)
{
// If there are ko
if (r - l > k)
return -1;
// Find maximum in range L and R
int maximum = rangemax(0, n - 1, l, r, 0, b, a, n);
// If maximum is 0
if (maximum < 0)
maximum = 0;
// Find the prefix sum
int rangesum = prefix[r];
// If not first element
if (l > 0)
rangesum -= prefix[l - 1];
// Get the answer
int answer = rangesum + (k - (r - l)) * maximum;
return answer;
}
// Function that solves the queries
static void solveQueries(int n, int []a, int []b,
int []prefix, int [,]queries, int q)
{
// Solve all the queries
for (int i = 0; i < q; i++)
{
int ans = solveQuery(queries[i,0], queries[i,1],
queries[i,2], n, a, b, prefix);
if (ans != -1)
Console.WriteLine(ans);
else
Console.WriteLine("No" );
}
}
// Function to find the prefix sum
static void findPrefixSum(int []prefix, int []a, int n)
{
prefix[0] = a[0];
for (int i = 1; i < n; i++)
{
prefix[i] = prefix[i - 1] + a[i];
}
}
// Driver code
public static void Main(String[] args)
{
int []a = { 1, 3, 2, -4, -5 };
int n = a.Length;
// Array for segment tree
int []b = new int[5 * n];
// Create segment tree
tree(0, n - 1, 0, b, a, n);
int []prefix = new int[n];
// Fill prefix sum array
findPrefixSum(prefix, a, n);
// Queries
int [,]queries = { { 0, 2, 2 },
{ 0, 2, 4 },
{ 3, 4, 1 },
{ 0, 4, 2 } };
int q = queries.GetLength(0);
solveQueries(n, a, b, prefix, queries, q);
}
}
// This code has been contributed by 29AjayKumar
6
12
-9
No
时间复杂度:每个查询O(Log N)。
辅助空间: O(N log N)
如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。