我们给定2 * N – 1个整数。我们需要检查是否有可能为来自这些整数的N个不同整数的数组构造一个范围最小查询段树。如果是这样,我们必须输出段树数组。 N被赋予2的幂。
RMQ段树是一个二叉树,其中的每个节点等于其子节点的最小值。这种类型的树用于有效地找到给定范围内的元素的最小值。
Input : 1 1 1 1 2 2 3 3 3 4 4 5 6 7 8
Output : 1 1 3 1 2 3 4 1 5 2 6 3 7 4 8
The segment tree is shown below
Input : -381 -460 -381 95 -460 855 -242
405 -460 982 -381 -460 95 981 855
Output : -460 -460 -381 -460 95 -381 855
-460 -242 95 405 -381 981 855 982
By constructing a segment tree from the output,
we can see that it a valid tree for RMQ and the
leaves are all distinct integers.
我们首先要做的是遍历给定的整数,计算每个数字的出现次数,然后按值对它们进行排序。在C++中,我们可以使用数据结构图,该图按排序顺序存储元素。
现在,我们为分段树的每个可能级别维护一个队列。我们将树的初始根(数组索引0)放入队列中以获取最大级别。然后,我们将最小的元素插入最左边的节点。然后,我们将这些节点与主树分离。分离节点时,我们将创建高度为h – 1的新树,其中h为当前节点的高度。我们可以在图2中看到这一点。我们将新树的根节点根据其高度插入适当的队列中。
我们遍历每个元素,根据该元素的出现次数获得一棵适当高度的树。如果在任何时候都不存在这样的树,则无法创建段树。
CPP
// C++ Program to Create RMQ Segment Tree
#include
using namespace std;
// Returns true if it is possible to construct
// a range minimum segment tree from given array.
bool createTree(int arr[], int N)
{
// Store the height of the final tree
const int height = log2(N) + 1;
// Container to sort and store occurrences of elements
map multi;
// Insert elements into the container
for (int i = 0; i < 2 * N - 1; ++i)
++multi[arr[i]];
// Used to store new subtrees created
set Q[height];
// Insert root into set
Q[height - 1].emplace(0);
// Iterate through each unique element in set
for (map::iterator it = multi.begin();
it != multi.end(); ++it)
{
// Number of occurrences is greater than height
// Or, no subtree exists that can accomodate it
if (it->second > height || Q[it->second - 1].empty())
return false;
// Get the appropriate subtree
int node = *Q[it->second - 1].begin();
// Delete the subtree we grabbed
Q[it->second - 1].erase(Q[it->second - 1].begin());
int level = 1;
for (int i = node; i < 2 * N - 1;
i = 2 * i + 1, ++level)
{
// Insert new subtree created into root
if (2 * i + 2 < 2 * N - 1)
Q[it->second - level - 1].emplace(2 * i + 2);
// Insert element into array at position
arr[i] = it->first;
}
}
return true;
}
// Driver program
int main()
{
int N = 8;
int arr[2 * N - 1] = {1, 1, 1, 1, 2, 2,
3, 3, 3, 4, 4, 5, 6, 7, 8};
if (createTree(arr, N))
{
cout << "YES\n";
for (int i = 0; i < 2 * N - 1; ++i)
cout << arr[i] << " ";
}
else
cout << "NO\n";
return 0;
}
Python3
# Python Program to Create RMQ Segment Tree
from typing import List
from math import log2
# Returns true if it is possible to construct
# a range minimum segment tree from given array.
def createTree(arr: List[int], N: int) -> bool:
# Store the height of the final tree
height = int(log2(N)) + 1
# Container to sort and store occurrences of elements
multi = {}
# Insert elements into the container
for i in range(2 * N - 1):
if arr[i] not in multi:
multi[arr[i]] = 0
multi[arr[i]] += 1
# Used to store new subtrees created
Q = [set() for _ in range(height)]
# Insert root into set
Q[height - 1].add(0)
# Iterate through each unique element in set
for k, v in multi.items():
# Number of occurrences is greater than height
# Or, no subtree exists that can accomodate it
if (v > height or len(Q[v - 1]) == 0):
return False
# Get the appropriate subtree
node = sorted(Q[v - 1])[0]
# Delete the subtree we grabbed
Q[v - 1].remove(sorted(Q[v - 1])[0])
level = 1
# for (int i = node; i < 2 * N - 1;
# i = 2 * i + 1, ++level)
i = node
while i < 2 * N - 1:
# Insert new subtree created into root
if (2 * i + 2 < 2 * N - 1):
Q[v - level - 1].add(2 * i + 2)
# Insert element into array at position
arr[i] = k
level += 1
i = 2 * i + 1
return True
# Driver program
if __name__ == "__main__":
N = 8
arr = [1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 6, 7, 8]
if (createTree(arr, N)):
print("YES")
# for (int i = 0; i < 2 * N - 1; ++i)
for i in range(2 * N - 1):
print(arr[i], end=" ")
else:
print("No")
# This code is contributed by sanjeev2552
输出:
YES
1 1 3 1 2 3 4 1 5 2 6 3 7 4 8