【pku3666】左偏树的应用、维护区间中位数

先说明,不是所有区间中位数都可以用左偏树维护的,本题是有特殊性的

拿到这道题,相信大部分人都想到了n^2的dp,我一开始也是笨笨地编了那个裸裸的程序,结果怎么都得200ms+

瞬间就有被第一版的0ms暴虐的感觉,忽然发现discuss里惊现某神牛的3字帖:左偏树

这才想到05hhy论文里ms提到了这个题,而且事实上那道题n的范围达到了100000!

哈哈,爽一把

好了,进入正题,简单讲讲这个高级算法

其实本题的解法是贪心,把整个序列分成若干块,每一块都改成那一块的中位数,而且保证每个块的中位数不小于前一个块的

那么就用左偏树维护这几个块的中位数,用栈来维护这些块

S1:(假设前i-1个数的块已经分好了)先把第i个数以一个数新开个块

S2:检查栈顶top的块的中位数是不是比top-1的要小,如果是则转S3,否则继续做下一个数i+1直到n个数都做完

S3:合并top和top-1两个块,转S2

至于中位数怎么维护,其实是很简单的

一个块如果有n个数,你只保留较小的(n+1)div 2个就可以了,用左偏树做个最大堆,最大的元素就是中位数

上述算法在论文里讲的更详细一点,你还可以参考一下那篇论文

本题要求个代价,那就还需要维护一些东西,论文里没有讲,其实也是很简单的

就每个左偏树维护4个东西

堆中元素个数now[i]、这些数的和s[i]、属于这个堆但被从堆中去掉的元素个数go[i]、这些数的和b[i]

最后ans=sigma每个块(该块中位数*now[i]-s[i]+b[i]-go[i]*中位数)

时间复杂度O(nlogn)

代码:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值