ATcoder Beginner 234D

题意:

给定n和k(1 <= k <= n <= 5e5),输入的n个数为1 ~ n的乱序,求前k个数,前k + 1个数,...,前n个数中第k大的数分别是多少

思路:

这题顺着想就不方便操作,因为要不断往序列里加入一些数,就算用优先队列也处理不了5e5的数据量,根据每次更新的序列做O(n)的线性时间选择也不现实,都是很繁琐且细节难实现的做法。

但是倒着处理就很顺手,我们可以先处理前n个数也就是所有数中的第k大,因为这n个数分别就是1~n,所以n个数里的第k大一定是 ans = n - k + 1。然后我们要找前n-1个数中的第k大,看下面的样例分析:

1)如果第n个数比当前的ans小,那么就算移除它也不影响当前ans在前n-1个数中的地位,也就是第k大依然是现在的ans

2)反之从长度为len的序列变到长度为len - 1的序列所要去掉的数如果比当前的ans大,那么去掉它以后在新序列里选第k大的时候,因为少了一个较大者,我们当前的ans也应该前移一位,能够前移的前提是这个数没被去掉过,因为去掉了以后他就不在新的序列中了,所以我们要给每次去掉的数打标记

3)那我们最后看一下细节问题,就是取等的情况,每次缩短序列长度要去掉的数正好等于当前ans的时候,我们也只需要直接前移一个数就可以了,与 2)同理,因为这个数已经用过被打标记了,那么就不可能让当前ans保持它

AC代码:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值