1. 题目

传送门= ̄ω ̄=

大意:给你一个数组和一堆询问,询问有三个参数l,r,k,要你输出数组区间[l,r]中排名第k的数字是多少

出题人你个傻逼又不说数据组数范围不然分块也能过结果你卡得我线段树不打读入优化都不一定能过,还必须打inline信不信我切了你的小鸡鸡╭(╯^╰)╮

2. 题解

首先简单讲下分块的写法吧

先分块,再对每个块排序,最后二分答案,对于每个枚举出的答案,在块内二分、块外暴力,算出它的排名,最后就可以确定答案了。

代码长这样(Warning:会TLE!):

上面那个理论上没错,只是会TLE

所以我们必须打线段树。

线段树嘛,维护区间。每个节点都会对应着一个区间,那我们就让每个节点里有一个数组,这个数组就是它对应的区间排序后的样子。然后我们二分答案以后检测答案是否合法,就直接找到区间对应的节点们,在节点的数组里二分找到当前答案在这个区间里排第几,最后加在一起就是它的排名了。

区间排序就在建树时用归并排序搞掉了。

至于每个节点要对应一个数组,直接用int的话空间太大,$N^2$的空间复杂度,无法接受。而开vector又太慢了。所以就搞个“公共储存池”(其实是我瞎YY出的名字,就是个公共数组而已),每个节点记录在这个公共数组里它所占用的数组左端点编号,数组右端点编号。这样空间复杂度是$NlogN$的。

这样每次查询是$log^3 N$的。最后复杂度就是$Mlog^3 N$的,总共复杂度就是$TMlog^3 N$的。

代码: