📌  相关文章
📜  在前N个自然数的置换中找到子数组的数量,以使它们的中位数为M

📅  最后修改于: 2021-05-05 02:03:12             🧑  作者: Mango

给定[]含有第一N的自然数的排列的整数中号≤N的阵列ARR。任务是找到子阵列的数量,以使序列的中位数为M。
序列的中位数是元素的值,该元素在以非降序排序后位于序列的中间。如果序列的长度是偶数,则使用两个中间元素的左侧。

例子:

方法:当且仅当M属于段p [l..r]时,中位数等于M,并且less =大于小于=较大– 1,其中p [l..r]中元素的数量较少严格小于M和更大是p中是严格大于M.在这里,我们使用了一个事实,即p是一个置换(上p元素[l..r]的数目[l..r]正好有一个出现M)。

换句话说,M属于p [l..r],且值大–小等于0或1。

计算前缀求和sum [0..n],其中sum [i]在长度i的前缀上(即在子数组p [0..i-1]上) -小于或等于更大的值。对于固定值r,很容易计算出p [l..r]合适的l的数量。首先,检查M是否在[0..r]上相遇。有效值l是这样的索引:[0..l-1]上没有M,并且sum [l] = sum [r]或sum [r] = sum [l] +1。

让我们为每个值在M的左边保留一些前缀和sum [i]。我们可以只使用一个映射c,其中c [s]是多个这样的索引l,sum [l] = s和l在m的左边。

因此,对于每个p [0..r]包含m的r,做ans + = c [sum] + c [sum – 1],其中sum是当前值Greater -less

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
  
// Function to return the count of sub-arrays
// in the given permutation of first n natural
// numbers such that their median is m
int segments(int n, int p[], int m)
{
    map c;
    c[0] = 1;
    bool has = false;
    int sum = 0;
    long long ans = 0;
    for (int r = 0; r < n; r++) {
  
        // If element is less than m
        if (p[r] < m)
            sum--;
  
        // If element greater than m
        else if (p[r] > m)
            sum++;
  
        // If m is found
        if (p[r] == m)
            has = true;
  
        // Count the answer
        if (has)
            ans += c[sum] + c[sum - 1];
  
        // Increment sum
        else
            c[sum]++;
    }
  
    return ans;
}
  
// Driver code
int main()
{
    int a[] = { 2, 4, 5, 3, 1 };
    int n = sizeof(a) / sizeof(a[0]);
    int m = 4;
    cout << segments(n, a, m);
  
    return 0;
}


Java
// Java implementation of the approach 
import java.util.HashMap;
  
class GFG 
{
  
    // Function to return the count of sub-arrays
    // in the given permutation of first n natural
    // numbers such that their median is m
    public static int segments(int n, int[] p, int m)
    {
        HashMap c = new HashMap<>();
        c.put(0, 1);
        boolean has = false;
        int sum = 0;
        int ans = 0;
        for (int r = 0; r < n; r++) 
        {
  
            // If element is less than m
            if (p[r] < m)
                sum--;
  
            // If element greater than m
            else if (p[r] > m)
                sum++;
  
            // If m is found
            if (p[r] == m)
                has = true;
  
            // Count the answer
            if (has)
                ans += (c.get(sum) == null ? 0 : 
                        c.get(sum)) + 
                       (c.get(sum - 1) == null ? 0 : 
                        c.get(sum - 1));
  
            // Increment sum
            else
                c.put(sum, c.get(sum) == null ? 1 : 
                           c.get(sum) + 1);
        }
        return ans;
    }
  
    // Driver code
    public static void main(String[] args) 
    {
        int[] a = { 2, 4, 5, 3, 1 };
        int n = a.length;
        int m = 4;
        System.out.println(segments(n, a, m));
    }
}
  
// This code is contributed by
// sanjeev2552


Python3
# Python3 implementation of the approach
  
# Function to return the count of sub-arrays
# in the given permutation of first n natural
# numbers such that their median is m
def segments(n, p, m):
  
    c = dict()
  
    c[0] = 1
  
    has = False
  
    Sum = 0
  
    ans = 0
  
    for r in range(n):
  
        # If element is less than m
        if (p[r] < m):
            Sum -= 1
  
        # If element greater than m
        elif (p[r] > m):
            Sum += 1
  
        # If m is found
        if (p[r] == m):
            has = True
  
        # Count the answer
        if (has):
            if(Sum in c.keys()):
                ans += c[Sum]
            if Sum-1 in c.keys():
                ans += c[Sum - 1] 
  
        # Increment Sum
        else:
            c[Sum] = c.get(Sum, 0) + 1
  
    return ans
  
# Driver code
a = [2, 4, 5, 3, 1]
n = len(a)
m = 4
print(segments(n, a, m))
  
# This code is contributed by mohit kumar


C#
// C# implementation of the approach 
using System;
using System.Collections.Generic;             
  
class GFG 
{
  
    // Function to return the count of sub-arrays
    // in the given permutation of first n natural
    // numbers such that their median is m
    public static int segments(int n, int[] p, int m)
    {
        Dictionary c = new Dictionary();
        c.Add(0, 1);
        bool has = false;
        int sum = 0;
        int ans = 0;
        for (int r = 0; r < n; r++) 
        {
  
            // If element is less than m
            if (p[r] < m)
                sum--;
  
            // If element greater than m
            else if (p[r] > m)
                sum++;
  
            // If m is found
            if (p[r] == m)
                has = true;
  
            // Count the answer
            if (has)
                ans += (!c.ContainsKey(sum) ? 0 : 
                         c[sum]) + 
                    (!c.ContainsKey(sum - 1) ? 0 : 
                      c[sum - 1]);
  
            // Increment sum
            else
                c.Add(sum, !c.ContainsKey(sum) ? 1 : 
                            c[sum] + 1);
        }
        return ans;
    }
  
    // Driver code
    public static void Main(String[] args) 
    {
        int[] a = { 2, 4, 5, 3, 1 };
        int n = a.Length;
        int m = 4;
        Console.WriteLine(segments(n, a, m));
    }
}
  
// This code is contributed by 29AjayKumar


PHP
 $m) 
            $sum++; 
  
        // If m is found 
        if ($p[$r] == $m) 
            $has = true; 
  
        // Count the answer 
        if ($has) 
            $ans += $c[$sum] + $c[$sum - 1]; 
  
        // Increment sum 
        else
            $c[$sum]++; 
    } 
  
    return $ans; 
} 
  
// Driver code 
$a = array( 2, 4, 5, 3, 1 ); 
$n = count($a);
$m = 4; 
  
echo segments($n, $a, $m); 
  
// This code is contributed by Ryuga
?>


输出:
4