`
feiliboos
  • 浏览: 662465 次
文章分类
社区版块
存档分类
最新评论

NOI2010.Day1.T2.超级钢琴

 
阅读更多

题目大意:

在n个数字中找出k个不相同的长度在l-r之间的连续子序列,使得权值和最大(n<=500000,k<=500000)


昨天膜拜了一下10年的年鉴

这道题合法的子序列是非常多的,如果朴素显然是无法做出这道题

有一个非常美妙的想法,对于给定的起点,起点的权值已知了,子序列的个数是确定的

那么记录一下前缀和s[i],对于给定的起点,实际上就是询问起点所代表的那一段区间的最大权值,这个就是RMQ问题,ST算法可以在O(nlogn)-O(1)的时间完成

那么对于每个点i,有一个pos[i]指向i所对应的区间里s[j]的最大值

用堆来维护一个五元组(st,idx,l,r,v),st代表起点,idx代表起点对应的区间里最大值的下标,l,r代表对应的区间,v代表这个子序列的值

那么我们每次从堆中取出这样一个五元组以后,要将区间分裂,因为i-j这个区间不能取了,所以要将(st,idx,l,r,v)分裂为(st,idx‘,l,idx-1,v),(st,idx’‘,idx+1,r,v)两个区间

由于最多取k个,堆中最多有n+k个元素,时间复杂度为O((n+k)log(n+k))


具体实现看代码


还有一种方法不分裂区间,而是转而记录应该取这个区间里第k大的元素,这需要用到划分树or归并树这一数据结构,由于多年不写已经忘记……

so,这道题可以作为划分树or归并树的练习题,到时候再写一次




划分树版本:



分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics