【GDOI2013模拟1】删数字

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Larry1118/article/details/87892692

这题我们发现,只有在剩下的数是一段连续的数的时候才是最优的。

所以,这题我们用桶来做。
之前用线段树来做,结果T︿( ̄︶ ̄)︿了。。。
我们用桶维护区间最小值,然后在记录一下这个差值的位置。
不断地搞这东东就可以了。
上标:

#include<cstdio>
#include<algorithm>
#define N 1000010
using namespace std;
int n,K,a[N],d[N],fr[N],ans=(1<<30),tot=0;

inline int read()
{
	int x=0,f=0; char c=getchar();
	while (c<'0' || c>'9') f=(c=='-') ? 1:f,c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return f ? -x:x;
}

void up(int x)
{
	while (x>1 && d[x]<d[x>>1])
		swap(d[x],d[x>>1]),swap(fr[x],fr[x>>1]),x>>=1;
}

void down()
{
	int x=1,t=x<<1;
	if (d[t]>d[t+1] && t<tot) t++;
	while (t<=tot)
	{
		if (d[t]<d[x]) 
			swap(d[t],d[x]),swap(fr[t],fr[x]),x=t;
		else break;
		t=x<<1;
		if (d[t]>d[t+1] && t<tot) t++;
	}
}

int main()
{
	n=read(),K=n-read();
	for (int i=1;i<=n;i++) a[i]=read();
	sort(a+1,a+n+1);
	for (int i=2;i<=K;i++)
		d[++tot]=a[i]-a[i-1],fr[tot]=i,up(tot);
	ans=a[K]-a[1]+d[1];
	for (int i=K+1;i<=n;i++)
	{
		d[++tot]=a[i]-a[i-1],fr[tot]=i,up(tot);
		while (fr[1]<=i-K+1) d[1]=d[tot],fr[1]=fr[tot],tot--,down();
		if (d[1]+a[i]-a[i-K+1]<ans) ans=d[1]+a[i]-a[i-K+1];
	}
	printf("%d\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Larry1118/article/details/87892692