给定前N个自然数的排列P ,任务是对索引对(i,j)进行计数,使得P [i] + P [j] = max(P [x]) ,其中i≤x≤j 。
例子:
Input: P[] = {3, 4, 1, 5, 2}
Output: 2
Only valid index pairs are (0, 4) and (0, 2)
Input: P[] = {1, 3, 2}
Output: 1
天真的方法:我们可以通过迭代所有可能的对(i,j)来解决此问题,并且每次在它们之间获得最大值。该方法的时间复杂度将为O(n 3 ) 。
高效的方法:将最大元素固定在一个线段上,然后对其左侧或右侧的元素进行迭代。如果当前最大值是x,而我们找到的元素是y,则检查元素xy是否可以与y形成子段(即x是分段上的最大值)
在y和xy之间)。这适用于O(n * n)
但是,如果我们可以预先计算x为最大元素的段的边界,并且始终选择对段的较小部分进行迭代,则时间复杂度将降低为O(nlogn)。
因为每个元素的处理时间都不会超过logn次,所以如果我们在大小为m的段中对其进行处理,则它的较小部分将包含不超过m / 2个元素(稍后我们将对其进行处理,而该段的较小部分最多包含m / 4个元素,依此类推..)。
下面是上述方法的实现:
C++
// CPP implementation of the approach
#include
using namespace std;
// Function to return the count of
// required index pairs
int Count_Segment(int p[], int n)
{
// To store the required count
int count = 0;
// Array to store the left elements
// upto which current element is maximum
int upto[n + 1];
for(int i = 0; i < n + 1; i++)
upto[i] = 0;
// Iterating through the whole permutation
// except first and last element
int j = 0,curr = 0;
for (int i = 1; i < n + 1; i++)
{
// If current element can be maximum
// in a subsegment
if (p[i] > p[i - 1] and p[i] > p[i + 1])
{
// Current maximum
curr = p[i];
// Iterating for smaller values then
// current maximum on left of it
j = i - 1;
while (j >= 0 and p[j] < curr)
{
// Storing left borders
// of the current maximum
upto[p[j]]= curr;
j -= 1;
}
// Iterating for smaller values then
// current maximum on right of it
j = i + 1;
while (j < n and p[j] < curr)
{
// Condition satisfies
if (upto[curr-p[j]] == curr)
count += 1;
j+= 1;
}
}
}
// Return count of subsegments
return count;
}
// Driver Code
int main()
{
int p[] = {3, 4, 1, 5, 2};
int n = sizeof(p)/sizeof(p[0]);
cout << (Count_Segment(p, n));
return 0;
}
// This code is contributed by
// Surendra_Gangwar
Java
// Java implementation of the approach
import java.util.*;
class GFG
{
// Function to return the count of
// required index pairs
static int Count_Segment(int p[], int n)
{
// To store the required count
int count = 0;
// Array to store the left elements
// upto which current element is maximum
int []upto = new int[n + 1];
for(int i = 0; i < n + 1; i++)
upto[i] = 0;
// Iterating through the whole permutation
// except first and last element
int j = 0,curr = 0;
for (int i = 1; i < n ; i++)
{
// If current element can be maximum
// in a subsegment
if (p[i] > p[i - 1] && p[i] > p[i + 1])
{
// Current maximum
curr = p[i];
// Iterating for smaller values then
// current maximum on left of it
j = i - 1;
while (j >= 0 && p[j] < curr)
{
// Storing left borders
// of the current maximum
upto[p[j]]= curr;
j -= 1;
}
// Iterating for smaller values then
// current maximum on right of it
j = i + 1;
while (j < n && p[j] < curr)
{
// Condition satisfies
if (upto[curr-p[j]] == curr)
count += 1;
j+= 1;
}
}
}
// Return count of subsegments
return count;
}
// Driver Code
public static void main(String[] args)
{
int p[] = {3, 4, 1, 5, 2};
int n = p.length;
System.out.println(Count_Segment(p, n));
}
}
/* This code contributed by PrinciRaj1992 */
Python
# Python3 implementation of the approach
# Function to return the count of
# required index pairs
def Count_Segment(p, n):
# To store the required count
count = 0
# Array to store the left elements
# upto which current element is maximum
upto = [False]*(n + 1)
# Iterating through the whole permutation
# except first and last element
for i in range(1, n-1):
# If current element can be maximum
# in a subsegment
if p[i]>p[i-1] and p[i]>p[i + 1]:
# Current maximum
curr = p[i]
# Iterating for smaller values then
# current maximum on left of it
j = i-1
while j>= 0 and p[j]
C#
// C# implementation of the approach
using System;
class GFG
{
// Function to return the count of
// required index pairs
static int Count_Segment(int []p, int n)
{
// To store the required count
int count = 0;
// Array to store the left elements
// upto which current element is maximum
int []upto = new int[n + 1];
for(int i = 0; i < n + 1; i++)
upto[i] = 0;
// Iterating through the whole permutation
// except first and last element
int j = 0,curr = 0;
for (int i = 1; i < n ; i++)
{
// If current element can be maximum
// in a subsegment
if (p[i] > p[i - 1] && p[i] > p[i + 1])
{
// Current maximum
curr = p[i];
// Iterating for smaller values then
// current maximum on left of it
j = i - 1;
while (j >= 0 && p[j] < curr)
{
// Storing left borders
// of the current maximum
upto[p[j]]= curr;
j= j - 1;
}
// Iterating for smaller values then
// current maximum on right of it
j = i + 1;
while (j < n && p[j] < curr)
{
// Condition satisfies
if (upto[curr-p[j]] == curr)
count += 1;
j= j+ 1;
}
}
}
// Return count of subsegments
return count;
}
// Driver Code
static public void Main ()
{
int []p = {3, 4, 1, 5, 2};
int n = p.Length;
Console.WriteLine(Count_Segment(p, n));
}
}
/* This code contributed by ajit*/
输出:
2