题意:给定一个长度为n的数组与m个查询。第i个查询要求输出数组下标区间[li,ri]内的数之间的距离(差的绝对值)的最小值。
分析:离线处理查询。将查询区间按右端点从小到大排序,维护一个数据结构,使得将数组元素a1,a2,...,ai插入到数据结构之后能够快速查询以ai为右端点的查询区间的答案。考虑ai对查询区间的贡献,设d=|ai-aj|(j<i),则对于满足l≤j,r=a[i]的查询区间[l,r],有查询区间[l,r]的答案≤d。因此可以用线段树来维护答案,线段树每个结点记录左端点处于对应范围内时(当右端点 为ai时)的查询区间的上确界。
若暴力处理ai对查询区间的贡献,则时间复杂度为O(n),这显然是不可接受的。不妨先设a1,a2,...,ai-1均大于等于ai(一般情况下处理2次即可),则在计算完元素对(ai,ai-1)对查询区间的贡献后,设下一个选取的元素对为(ai,aj),则aj应满足aj≤(ai+ai-1)/2。这是因为:1.aj≥ai-1时元素对(ai,aj)不优于元素对(ai,ai-1)的贡献;2.(ai+ai-1)/2≤aj≤ai-1时元素对(ai,aj)的贡献不优于元素对(ai-1,aj)的贡献。依次类推,计算ai对查询区间的贡献时间复杂度可以优化到O(lgn)。
下面讨论程序的实现。我们需要一个数据结构,使得能够快速求出数组下标在[1,j-1]范围内大小在范围[ai,(ai+aj)/2]内的下标最大的数。可以建一棵线段树,线段树的每个结点[l,r]存一个vector,vector里将al,al+1,...,ar按从小到大排序,然后就可以O(lgn^2)地完成这件事(官方题解似乎有O(lgn)的做法)。
代码:
#inclu