给定一个大小为N的二进制数组,范围在[l, r] 中,任务是找到给定范围内两个 1 之间的最大距离。
例子:
Input: arr = {1, 0, 0, 1}, l = 0, r = 3
Output: 3
In the given range from 0 to 3, first 1 lies at index 0 and last at index 3.
Hence, maximum distance = 3 – 0 = 3.
Input: arr = {1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0}, l = 3, r = 9
Output: 6
方法:我们将创建一个段树来解决这个问题。
- 线段树中的每个节点将具有最左边的 1 和最右边的 1 的索引以及一个整数,该整数包含子数组 {l, r} 中任何值为 1 的元素之间的最大距离。
- 现在,在这个线段树中,我们可以合并左右节点,如下所示:
- 如果左节点无效,则返回右节点。
- 如果右节点无效,则返回左节点。
- 一个节点是有效的,如果它包含至少一个 0,或至少一个 1。
- 如果左右节点都有效,则:
让,- l1 = 1 的最左边索引(-1 如果该间隔中不存在 0)
- r1 = 1 的最右边索引(如果 0 在该间隔中不存在,则为 -1)
- max1 = 两个 1 之间的最大距离
- 合并节点中 max1 的值将是左右节点中 max1 值的最大值的最大值,以及右节点中最右边索引 1 与左节点中最左边索引 1 之间的差值。
- 合并节点中 l1 的值如果不是 -1,则为左节点的 l1,否则为右节点的 l1。
- 合并节点中r1的值如果不是-1,则为右节点的r1,否则为左节点的r1。
- 然后,最后为了找到答案,我们只需要为给定的范围 {l, r} 调用查询函数。
下面是上述方法的实现:
C++
// C++ program to find the maximum
// distance between two elements
// with value 1 within a subarray (l, r)
#include
using namespace std;
// Structure for each node
// in the segment tree
struct node {
int l1, r1;
int max1;
} seg[100001];
// A utility function for
// merging two nodes
node task(node l, node r)
{
node x;
x.l1 = (l.l1 != -1) ? l.l1 : r.l1;
x.r1 = (r.r1 != -1) ? r.r1 : l.r1;
x.max1 = max(l.max1, r.max1);
if (l.l1 != -1 && r.r1 != -1)
x.max1 = max(x.max1, r.r1 - l.l1);
return x;
}
// A recursive function that constructs
// Segment Tree for given string
void build(int qs, int qe, int ind, int arr[])
{
// If start is equal to end then
// insert the array element
if (qs == qe) {
if (arr[qs] == 1) {
seg[ind].l1 = seg[ind].r1 = qs;
seg[ind].max1 = INT_MIN;
}
else {
seg[ind].l1 = seg[ind].r1 = -1;
seg[ind].max1 = INT_MIN;
}
return;
}
int mid = (qs + qe) >> 1;
// Build the segment tree
// for range qs to mid
build(qs, mid, ind << 1, arr);
// Build the segment tree
// for range mid+1 to qe
build(mid + 1, qe, ind << 1 | 1, arr);
// merge the two child nodes
// to obtain the parent node
seg[ind] = task(
seg[ind << 1],
seg[ind << 1 | 1]);
}
// Query in a range qs to qe
node query(int qs, int qe,
int ns, int ne, int ind)
{
node x;
x.l1 = x.r1 = -1;
x.max1 = INT_MIN;
// If the range lies in this segment
if (qs <= ns && qe >= ne)
return seg[ind];
// If the range is out of the bounds
// of this segment
if (ne < qs || ns > qe || ns > ne)
return x;
// Else query for the right and left
// child node of this subtree
// and merge them
int mid = (ns + ne) >> 1;
node l = query(qs, qe, ns,
mid, ind << 1);
node r = query(qs, qe,
mid + 1, ne,
ind << 1 | 1);
x = task(l, r);
return x;
}
// Driver code
int main()
{
int arr[] = { 1, 1, 0,
1, 0, 1,
0, 1, 0,
1, 0, 1,
1, 0 };
int n = sizeof(arr) / sizeof(arr[0]);
int l = 3, r = 9;
// Build the segment tree
build(0, n - 1, 1, arr);
// Query in range 3 to 9
node ans = query(l, r, 0, n - 1, 1);
cout << ans.max1 << "\n";
return 0;
}
Java
// Java program to find the maximum
// distance between two elements
// with value 1 within a subarray (l, r)
import java.util.*;
class GFG{
// Structure for each node
// in the segment tree
static class node {
int l1, r1;
int max1;
}
static node []seg = new node[100001];
// A utility function for
// merging two nodes
static node task(node l, node r)
{
node x = new node();
x.l1 = (l.l1 != -1) ? l.l1 : r.l1;
x.r1 = (r.r1 != -1) ? r.r1 : l.r1;
x.max1 = Math.max(l.max1, r.max1);
if (l.l1 != -1 && r.r1 != -1)
x.max1 = Math.max(x.max1, r.r1 - l.l1);
return x;
}
// A recursive function that constructs
// Segment Tree for given String
static void build(int qs, int qe, int ind, int arr[])
{
// If start is equal to end then
// insert the array element
if (qs == qe) {
if (arr[qs] == 1) {
seg[ind].l1 = seg[ind].r1 = qs;
seg[ind].max1 = Integer.MIN_VALUE;
}
else {
seg[ind].l1 = seg[ind].r1 = -1;
seg[ind].max1 = Integer.MIN_VALUE;
}
return;
}
int mid = (qs + qe) >> 1;
// Build the segment tree
// for range qs to mid
build(qs, mid, ind << 1, arr);
// Build the segment tree
// for range mid+1 to qe
build(mid + 1, qe, ind << 1 | 1, arr);
// merge the two child nodes
// to obtain the parent node
seg[ind] = task(
seg[ind << 1],
seg[ind << 1 | 1]);
}
// Query in a range qs to qe
static node query(int qs, int qe,
int ns, int ne, int ind)
{
node x = new node();
x.l1 = x.r1 = -1;
x.max1 = Integer.MIN_VALUE;
// If the range lies in this segment
if (qs <= ns && qe >= ne)
return seg[ind];
// If the range is out of the bounds
// of this segment
if (ne < qs || ns > qe || ns > ne)
return x;
// Else query for the right and left
// child node of this subtree
// and merge them
int mid = (ns + ne) >> 1;
node l = query(qs, qe, ns,
mid, ind << 1);
node r = query(qs, qe,
mid + 1, ne,
ind << 1 | 1);
x = task(l, r);
return x;
}
// Driver code
public static void main(String[] args)
{
for(int i= 0; i < 100001; i++)
seg[i] = new node();
int arr[] = { 1, 1, 0,
1, 0, 1,
0, 1, 0,
1, 0, 1,
1, 0 };
int n = arr.length;
int l = 3, r = 9;
// Build the segment tree
build(0, n - 1, 1, arr);
// Query in range 3 to 9
node ans = query(l, r, 0, n - 1, 1);
System.out.print(ans.max1+ "\n");
}
}
// This code is contributed by Rajput-Ji
Python3
# Python3 program to find the maximum
# distance between two elements
# with value 1 within a subarray (l, r)
import sys
# Structure for each node
# in the segment tree
class node():
def __init__(self):
self.l1 = 0
self.r1 = 0
self.max1 = 0
seg = [node() for i in range(100001)]
# A utility function for
# merging two nodes
def task(l, r):
x = node()
x.l1 = l.l1 if (l.l1 != -1) else r.l1
x.r1 = r.r1 if (r.r1 != -1) else l.r1
x.max1 = max(l.max1, r.max1)
# If both the nodes are valid
if (l.r1 != -1 and r.l1 != -1):
x.max1 = max(x.max1, r.r1 - l.l1)
return x
# A recursive function that constructs
# Segment Tree for given string
def build(qs, qe, ind, arr):
# If start is equal to end then
# insert the array element
if (qs == qe):
if (arr[qs] == 1):
seg[ind].l1 = seg[ind].r1 = qs
seg[ind].max1 = -sys.maxsize
else:
seg[ind].l1 = seg[ind].r1 = -1
seg[ind].max1 = -sys.maxsize
return
mid = (qs + qe) >> 1
# Build the segment tree
# for range qs to mid
build(qs, mid, ind << 1, arr)
# Build the segment tree
# for range mid+1 to qe
build(mid + 1, qe, ind << 1 | 1, arr)
# Merge the two child nodes
# to obtain the parent node
seg[ind] = task(seg[ind << 1],
seg[ind << 1 | 1])
# Query in a range qs to qe
def query(qs, qe, ns, ne, ind):
x = node()
x.l1 = x.r1 = -1
x.max1 = -sys.maxsize
# If the range lies in this segment
if (qs <= ns and qe >= ne):
return seg[ind]
# If the range is out of the bounds
# of this segment
if (ne < qs or ns > qe or ns > ne):
return x
# Else query for the right and left
# child node of this subtree
# and merge them
mid = (ns + ne) >> 1
l = query(qs, qe, ns, mid, ind << 1)
r = query(qs, qe, mid + 1, ne, ind << 1 | 1)
x = task(l, r)
return x
# Driver code
if __name__=="__main__":
arr = [ 1, 1, 0, 1, 0, 1, 0,
1, 0, 1, 0, 1, 1, 0 ]
n = len(arr)
l = 3
r = 9
# Build the segment tree
build(0, n - 1, 1, arr)
# Query in range 3 to 9
ans = query(l, r, 0, n - 1, 1)
print(ans.max1)
# This code is contributed by rutvik_56
C#
// C# program to find the maximum
// distance between two elements
// with value 1 within a subarray (l, r)
using System;
class GFG{
// Structure for each node
// in the segment tree
class node {
public int l1, r1;
public int max1;
}
static node []seg = new node[100001];
// A utility function for
// merging two nodes
static node task(node l, node r)
{
node x = new node();
x.l1 = (l.l1 != -1) ? l.l1 : r.l1;
x.r1 = (r.r1 != -1) ? r.r1 : l.r1;
x.max1 = Math.Max(l.max1, r.max1);
if (l.l1 != -1 && r.r1 != -1)
x.max1 = Math.Max(x.max1, r.r1 - l.l1);
return x;
}
// A recursive function that constructs
// Segment Tree for given String
static void build(int qs, int qe, int ind, int []arr)
{
// If start is equal to end then
// insert the array element
if (qs == qe) {
if (arr[qs] == 1) {
seg[ind].l1 = seg[ind].r1 = qs;
seg[ind].max1 = int.MinValue;
}
else {
seg[ind].l1 = seg[ind].r1 = -1;
seg[ind].max1 = int.MinValue;
}
return;
}
int mid = (qs + qe) >> 1;
// Build the segment tree
// for range qs to mid
build(qs, mid, ind << 1, arr);
// Build the segment tree
// for range mid+1 to qe
build(mid + 1, qe, ind << 1 | 1, arr);
// merge the two child nodes
// to obtain the parent node
seg[ind] = task(
seg[ind << 1],
seg[ind << 1 | 1]);
}
// Query in a range qs to qe
static node query(int qs, int qe,
int ns, int ne, int ind)
{
node x = new node();
x.l1 = x.r1 = -1;
x.max1 = int.MinValue;
// If the range lies in this segment
if (qs <= ns && qe >= ne)
return seg[ind];
// If the range is out of the bounds
// of this segment
if (ne < qs || ns > qe || ns > ne)
return x;
// Else query for the right and left
// child node of this subtree
// and merge them
int mid = (ns + ne) >> 1;
node l = query(qs, qe, ns,
mid, ind << 1);
node r = query(qs, qe,
mid + 1, ne,
ind << 1 | 1);
x = task(l, r);
return x;
}
// Driver code
public static void Main(String[] args)
{
for(int i = 0; i < 100001; i++)
seg[i] = new node();
int []arr = { 1, 1, 0,
1, 0, 1,
0, 1, 0,
1, 0, 1,
1, 0 };
int n = arr.Length;
int l = 3, r = 9;
// Build the segment tree
build(0, n - 1, 1, arr);
// Query in range 3 to 9
node ans = query(l, r, 0, n - 1, 1);
Console.Write(ans.max1+ "\n");
}
}
// This code is contributed by Princi Singh
输出:
6
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live