sicily 9162 RAZLIKA

来源:互联网 发布:centos 设置gateway 编辑:程序博客网 时间:2024/05/11 19:47
单调队列

题意:
给你一个n个元素的数组a,一个整数k,你要在数组中删去其中k个元素,使得剩下的元素的最大差值+最小差值最小

数据范围:
n<=1000000,元素ai∈[-5000000,5000000],1<=k<=n-2

思路:

使一个最大值最小,通常是二分答案.但一看这数据范围,只能用O(n)的算法了

这里有一个挺强的结论:如果将这个数组排序之后,删除两边的元素,也就是保留的元素是中间的一段连续的区间,这样必定能出最优解

当初想了一个更强的结论,可惜太强了,是上面的结论,加上只要是最大差值最小的若干个区间,答案必定是这些区间的最大差值+最小差值的其中一个

证明:

先将数组排序.假设存在不连续的序列,使得答案最小,设这个序列的开头和结尾是i和j,中间存在一个k是舍去的.那么我们知道最大差值肯定是a[j]-a[i],设最小差值是a[c]-a[c-1],那么a[c-1]和a[c]都是保留的元素.

假如c!=j,那么我们可以舍去a[j],然后保留a[k],这样做最大差值的话显然不会增加,最小差值也是,因为c!=j,删去j不影响最小的那对.

假如c==j,那么我们可以舍去a[i],然后保留a[k],同理这样最大差值不会增,又因为c==j,所以必然有c!=i和c!=i+1(j-i必定大于2,因为有k),这样的话删去i不影响最小差值
综上,填补一个k不会使答案增大,所以最小的答案必然可以对应一个连续的区间

证完这东西之后,就要O(n)解决这道题了.我们可以遍历左端点,由于长度固定,且递增,我们可以O(1)求出最大差值,但最小差值怎么办?枚举这区间相邻的每对元素就是O(n2)的喔

我们发现,左端点向右扫描的过程中,在候选的相邻每对元素中,越是左边而差值越大的是没用的.这里的没用是指这对元素到了后面也不会被选上做最小差值对.因为它又左差值又大,说明它右边有一对比它的差值要小的.这样的话,左端点继续扫描,假如这两对元素还在区间里,肯定不会选左边的,最起码会选右边.而当右边那对不在区间了,左边这对也不会在区间里了.因此,它是没用的.又左又大永远不用,不就是单调队列吗?!

我们先初始化单调队列,按越左越小单调,我是让左边是队尾,把左端点是0的区间的每对元素弄进单调队列,除了最后一对.

从左往右扫描左端点,看队尾最小的是否不在区间里了,不在的话要pop掉.然后考虑对应的区间的最后一对,不断地从队首pop掉差值大的(越左越大越没用),最后把自己放进队首.然后更新最大差值+最小差值,最小差值就是当前队尾的那对元素.

同时维护队首队尾是经典的单调队列问题,由于每对相邻的元素只会进队一次出队一次,因此单调队列的维护是整体O(n)的,所以最终复杂度就是O(n)

总结:往右扫描左端点,维护单调队列,更新最大差值+最小差值


0 0
原创粉丝点击