先决条件:段树
给定一个仅由 0 和 1 组成的二进制数组arr[]和一个由 K 个查询组成的二维数组Q[][] ,任务是在数组的 [L, R] 范围内找到两个 0 之间的最小距离每个查询 {L, R}。
例子:
Input: arr[] = {1, 0, 0, 1}, Q[][] = {{0, 2}}
Output: 1
Explanation:
Clearly, in the range [0, 2], the first 0 lies at index 1 and last at index 2.
Minimum distance = 2 – 1 = 1.
Input: arr[] = {1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0}, Q[][] = {{3, 9}, {10, 13}}
Output: 2 3
Explanation:
In the range [3, 9], the minimum distance between 0’s is 2 (Index 4 and 6).
In the range [10, 13], the minimum distance between 0’s is 3 (Index 10 and 13).
做法:思路是用一个segment tree来解决这个问题:
- 线段树中的每个节点都有最左边的 0 和最右边的 0 的索引,以及一个包含子数组 {L, R} 中 0 之间的最小距离的整数。
- 令 min 为两个零点之间的最小距离。然后,可以在形成线段树后找到 min 的值:
min = 最小值(左节点的 min 值,右节点的 min 值,以及右节点最左边索引 0 与左节点最右边索引 0 的差值)。 - 在计算并存储每个节点的最小距离后,所有查询都可以在对数时间内得到回答。
下面是上述方法的实现:
C++
// C++ program to find the minimum
// distance between two elements
// with value 0 within a subarray (l, r)
#include
using namespace std;
// Structure for each node
// in the segment tree
struct node {
int l0, r0;
int min0;
} seg[100001];
// A utility function for
// merging two nodes
node task(node l, node r)
{
node x;
x.l0 = (l.l0 != -1) ? l.l0 : r.l0;
x.r0 = (r.r0 != -1) ? r.r0 : l.r0;
x.min0 = min(l.min0, r.min0);
// If both the nodes are valid
if (l.r0 != -1 && r.l0 != -1)
// Computing the minimum distance to store
// in the segment tree
x.min0 = min(x.min0, r.l0 - l.r0);
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] == 0) {
seg[ind].l0 = seg[ind].r0 = qs;
seg[ind].min0 = INT_MAX;
}
else {
seg[ind].l0 = seg[ind].r0 = -1;
seg[ind].min0 = INT_MAX;
}
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.l0 = x.r0 = -1;
x.min0 = INT_MAX;
// 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]);
// Build the segment tree
build(0, n - 1, 1, arr);
// Queries
int Q[][2] = { { 3, 9 }, { 10, 13 } };
for (int i = 0; i < 2; i++) {
// Finding the answer for every query
// and printing it
node ans = query(Q[i][0], Q[i][1],
0, n - 1, 1);
cout << ans.min0 << endl;
}
return 0;
}
Java
// Java program to find the minimum
// distance between two elements
// with value 0 within a subarray (l, r)
class GFG{
// Structure for each Node
// in the segment tree
static class Node
{
int l0, r0;
int min0;
};
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.l0 = (l.l0 != -1) ? l.l0 : r.l0;
x.r0 = (r.r0 != -1) ? r.r0 : l.r0;
x.min0 = Math.min(l.min0, r.min0);
// If both the Nodes are valid
if (l.r0 != -1 && r.l0 != -1)
// Computing the minimum distance to store
// in the segment tree
x.min0 = Math.min(x.min0, r.l0 - l.r0);
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] == 0)
{
seg[ind].l0 = seg[ind].r0 = qs;
seg[ind].min0 = Integer.MAX_VALUE;
}
else
{
seg[ind].l0 = seg[ind].r0 = -1;
seg[ind].min0 = Integer.MAX_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.l0 = x.r0 = -1;
x.min0 = Integer.MAX_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;
// Build the segment tree
build(0, n - 1, 1, arr);
// Queries
int[][] Q = { { 3, 9 }, { 10, 13 } };
for(int i = 0; i < 2; i++)
{
// Finding the answer for every query
// and printing it
Node ans = query(Q[i][0], Q[i][1],
0, n - 1, 1);
System.out.println(ans.min0);
}
}
}
// This code is contributed by sanjeev2552
Python3
# Python3 program to find the minimum
# distance between two elements with
# value 0 within a subarray (l, r)
import sys
# Structure for each node
# in the segment tree
class node():
def __init__(self):
self.l0 = 0
self.r0 = 0
min0 = 0
seg = [node() for i in range(100001)]
# A utility function for
# merging two nodes
def task(l, r):
x = node()
x.l0 = l.l0 if (l.l0 != -1) else r.l0
x.r0 = r.r0 if (r.r0 != -1) else l.r0
x.min0 = min(l.min0, r.min0)
# If both the nodes are valid
if (l.r0 != -1 and r.l0 != -1):
# Computing the minimum distance to
# store in the segment tree
x.min0 = min(x.min0, r.l0 - l.r0)
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] == 0):
seg[ind].l0 = seg[ind].r0 = qs
seg[ind].min0 = sys.maxsize
else:
seg[ind].l0 = seg[ind].r0 = -1
seg[ind].min0 = 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.l0 = x.r0 = -1
x.min0 = 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)
# Build the segment tree
build(0, n - 1, 1, arr)
# Queries
Q = [ [ 3, 9 ], [ 10, 13 ] ]
for i in range(2):
# Finding the answer for every query
# and printing it
ans = query(Q[i][0], Q[i][1], 0,
n - 1, 1)
print(ans.min0)
# This code is contributed by rutvik_56
输出:
2
3
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live