此题就是要注意单调性
每到一个点就要更新这个点是否是 isable[]代表以这个点前的所有组是否能成我们要求的一些组
islead[]代表包括这个点以及这个点是否能成我们要求的一些组
然后就二分答案
每次检查islead[n]就好了
然后注意ablel是有单调性的这样就是nlogn了否则我们要nlogn*logn来做了
还看不懂的朋友阔以留言~~~~
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int isable[300020],islead[300020];
int v[300020];
int n,k;
int ablel;
bool isleadd(int limit,int num)
{
if(num>=k&&v[num]-v[1]<=limit)//前面只有一个组
{
if(ablel==-1)
ablel=num+1;
return true;
}
if(ablel!=-1)//如果不能保证只有一组我们就考虑多组了
{
while(num-ablel+1>=k)
{
if(isable[ablel]&&v[num]-v[ablel]<=limit)
return true;
ablel++;
}
}
return false;//多组都没有就false了
}
bool solve(int limit)
{
for(int i=1;i<=n;i++)
{
if(isleadd(limit,i))
islead[i]=1;
if(islead[i-1])
isable[i]=1;
}
if(islead[n])
return true;
else
return false;
}
int main()
{
scanf("%d%d",&n,&k);
ablel=-1;
int minn=1000000020;
int maxx=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&v[i]);
maxx=max(maxx,v[i]);
minn=min(minn,v[i]);
}
sort(v+1,v+1+n);
if(k!=1)
{
int l=0;
int r=maxx-minn;
while(l<r)
{
// cout<<"l:"<<l<<" "<<"r;"<<r<<endl;
int mid=(l+r)>>1;
if(solve(mid))
r=mid;
else
l=mid+1;
for(int i=1;i<=n;i++)
{
isable[i]=0;
islead[i]=0;
}
ablel=-1;
}
printf("%d\n",r);
}
else
printf("0\n");
return 0;
}