description
给你一个N 个数组成的序列V,要你删除其中K 个数,M 表示剩下的数字
中任意两个数的差值的最大值,m 表示最小差值,要你计算删除K 个数后,M+m
的最小值。
analysis
-
先把原序列排序,那么尾减去头肯定是最大差值
-
中间n−1n-1n−1个可能的最小差值用线段树维护最小值
-
kkk次枚举头尾各删去几个,记录答案就行了
-
时间复杂度O(nlog2n)O(n\log_2n)O(nlog2n)
code
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 1000005
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define O3 __attribute__((optimize("-O3")))
using namespace std;
ll a[MAXN],b[MAXN],tr[MAXN<<2];
ll n,k,ans=1000000007;
O3 inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
O3 inline ll min(ll x,ll y)
{
return x<y?x:y;
}
O3 inline void maketree(ll t,ll l,ll r)
{
if (l==r){tr[t]=b[l];return;}
ll mid=(l+r)>>1;
maketree(t<<1,l,mid),maketree((t<<1)+1,mid+1,r);
tr[t]=min(tr[t<<1],tr[(t<<1)+1]);
}
O3 inline ll query(ll t,ll l,ll r,ll x,ll y)
{
if (l==x && y==r)return tr[t];
ll mid=(l+r)>>1;
if (y<=mid)return query(t<<1,l,mid,x,y);
else if (x>mid)return query((t<<1)+1,mid+1,r,x,y);
else return min(query(t<<1,l,mid,x,mid),query((t<<1)+1,mid+1,r,mid+1,y));
}
O3 int main()
{
//freopen("T1.in","r",stdin);
n=read(),k=read();
fo(i,1,n)a[i]=read();
sort(a+1,a+n+1);
fo(i,1,n-1)b[i]=a[i+1]-a[i];
maketree(1,1,n-1);
fo(i,0,k)//头删去i个数
{
ll mx=a[n-(k-i)]-a[1+i],mn=query(1,1,n-1,1+i,n-(k-i)-1);
ans=min(ans,mx+mn);
}
printf("%lld\n",ans);
return 0;
}