3154. 【GDOI2013模拟1】删数字

14 篇文章 0 订阅
4 篇文章 0 订阅

Description

给你一个N 个数组成的序列V,要你删除其中K 个数,M 表示剩下的数字

中任意两个数的差值的最大值,m 表示最小差值,要你计算删除K 个数后,M+m

的最小值。

Input

第一行包含两个整数N(3<=N<=1,000,000)和K(1<=K<=N-2);

第二行包含N 个空格隔开的数, 表示给定的序列

V(-5,000,000<=Vi<=5,000,000)。

Output

输出M+m 的最小值。

Sample Input

输入1:

5 2

-3 -2 3 8 6

输入2:

6 2

-5 8 10 1 13 -1

输入3:

6 3

10 2 8 17 2 17

 

Sample Output

输出1:

7

输出2:

13

输出3:

6

Data Constraint

100%的数据 3<=N<=1,000,000,1<=K<=N-2),-5,000,000<=Vi<=5,000,000

Solution

题目大意就是让你求在一个序列中删除k个数,让你最小化这n-k个数的任意两个数的最大差值和最小差值之和。

一个贪心的策略就是我们肯定是先删除最大或最小的数,证明很简单,若我们删掉的不是最大或最小的数,那么最大差值不会变,任然是最大的数减去最小的数,但是最小的差值有可能增加,所以我们肯定不能每次删除除最大最小值之外的数。换言之,问题转化为:在一个n个数的序列中从前面和后面一共删除k个数,最小化这n-k个数的最大差值和最小差值之和。

一个暴力的方法就是首先将这n个数排序后,枚举前面删多少个数(i),那么后面就删了k-i个数,然后我们知道最大差值即为两边数之差,但最小值只能再O(n)求一次。时间复杂度O(n^2)。

考虑若何优化最小值,一个方法是用线段树,但是会超空间,一个可行的方案即为用单调队列,我们发现当因为我们的区间是不断向右移动的(形象理解一下),所以当有一个差值加进队列里时,我们发现比它大的都一定不是最小值,所以都可以删掉,这样我们就可以维护一个单调递增的序列,每次将队头的元素更新ans即可。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1000010
using namespace std;
int n,k,a[N],mi[N],q[N],l,r,ans=1<<30;
int read(){
	int w=1,x=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*w;
}
int main(){
	freopen("delete.in","r",stdin);
	freopen("delete.out","w",stdout);
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++) a[i]=read();
	sort(a+1,a+1+n);
	for(int i=1;i<=n-1;i++) mi[i]=a[i+1]-a[i];
	l=1;r=0;
	for(int i=1;i<=n;i++){
		while(l<=r&&q[l]<=i-n+k) l++;
		if(i>=n-k){
			ans=min(ans,a[i]-a[i-n+k+1]+mi[q[l]]);
		}
		while(l<=r&&mi[i]<mi[q[r]]) r--;
		q[++r]=i;
	}
	printf("%d\n",ans);
	return 0;
}


作者:zsjzliziyang 
QQ:1634151125 
转载及修改请注明 
本文地址:https://blog.csdn.net/zsjzliziyang/article/details/87893972

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值