主席树大好题……这道题让主席树不仅停留在了区间第k大上,而是让它能执行像线段树一样的操作。
首先我们先说点套路的事。求中位数有一个二分法,就是每次二分答案,把大于等于当前二分的数设为1,小于的设为-1,之后我们只要看和是否大于0就能判断限制二分的值是大是小。然后虽然区间是不确定的,但是我们要求最大的中位数,只要取中间固定的一段+左区间最大后缀+右区间最大前缀判断即可。
不过这样的话每次暴力的时候,查询是\(O(nlogn)\)的,再套上查询次数会超时。如何优化一下呢?如果我们用线段树对于每一个二分的值,都维护一下它当前的值和最大前后缀,这样的话我们就只需要\(O(log^2n)\)的复杂度来完成一次查询。但是这样会\(MLE\)。
然后在每两棵树之间,其实只有\(i-1\)发生了变化,从1变成了-1.这样的话我们就可以把这些线段树建成主席树,用主席树来实现线段树一样的操作就好了。注意这道题是把以当前这个数的值为根,以位置为值域,注意访问区间不要开小(我就因为这个大数据\(MLE\)),最开始建树的地方比较重要,我们需要开一个\(vector\)来把数的值一样,多次出现的数的位置都存起来,然后按照值的大小按顺序修改即可。
看一下代码。
#include #include #include #include #include #include #include #include