具有特定属性的范围内的最小数目

时间:2019-04-12 07:27:49

标签: c++ algorithm logic segment-tree

我有一个长度为N的对的向量。现在我有给定范围的Q个查询,让我们说L到R,找到第一个元素等于给定数K的对中第二个元素的最小值。

例如:

6个元素的

向量 [{2,5},{8,7},{2,3},{8,6},{2,1},{8,4}]

现在可查询:L = 3 R = 6(基于1的索引)和K = 8

答案为-> 4,对应于这对{8,4}

约束:

Q <= 100000

N <= 100000

对<= 100000

的第一个和第二个元素的值

我当时正在考虑采用段树方法,基本上是说成对的每个唯一的“第一”元素创建一个数组,其元素由原始对的“第二”元素组成,其中“第一”元素的值是v1;

现在为每个v1数组创建一个片段树,该树存储给定范围内的最小元素。

然后,我们可以简单地查询对应的“ v1”细分树以解决上述问题

我的方法很复杂,有人可以给我一个有效解决此问题的想法。

2 个答案:

答案 0 :(得分:1)

在这种情况下,您也可以使用地图,因为您所需的输出是第二个值。因此,将第一个值作为键,将第二个值作为键。 例如在3到6(基于1的索引)的给定范围内,您的地图将被跟踪。 2-> [3,1] 8-> [6,4] 现在,代码摘录看起来像。

map<int,vector<int>> m;// my map already contains the value, i suppose you know that.
vector<int> temp;
temp=m[k];//here k=8 as given
//find the smallest element in the given array temp.
// this method give O(nlogn) complexity

sort(temp.begin(),temp.end());
cout<<temp[0];

// this method will take complexity of o(n)
int min=INT_MAX;
for(int i=0;i<temp.size();i++)
{
    if(temp[i]<min)
    {
       min=temp[i];
     }

}
cout<<min;


答案 1 :(得分:0)

使用以下公式获取输入对并从中创建三元组T的数组:

(ai, bi) becomes ti = (ai, i, bi)

然后排序T。计算T上的段树,以便在知道O(log(n))子数组的开始和结束索引时可以获取T中第三字段的最小值。

定义常量:

int const nOO = std::numeric_limits<int>::min();
int const pOO = std::numeric_limits<int>::max();

接收查询时:(K, L, R)。将lower_bound()上的T(K, L, nOO)一起使用,以找到T子数组的开始,其中三元组的第一项为K或更大,并且索引更大或等于L

upper_bound()(K, R, pOO)一起使用以查找子数组的结尾(不包括结尾)。

现在,您可以使用段树来了解bi中的两个边界,以检索T的最小值。

对于每个查询,复杂度应为O(3*log(n)) = O(log(n)),对于O(n*log(n))数组和段树的初始构造,应为T