题意:平面上有n个点,将这n个点分成k部分,找到最小的X,使得每部分中任意两点距离都<=X。
转化一下就是求曼哈顿生成树的第k+1长的边,即第n-k短的边。
用上一题的代码(UVALive-3662)稍微改点就好了。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=100050;
const int INF=0x3f3f3f3f;
struct point{
int x,y,id;
}p[maxn];
bool cmp(point a,point b)
{
if(a.x!=b.x) return a.x<b.x;
else return a.y<b.y;
}
struct BIT
{
int min_val,pos;
void init()
{
min_val=INF;
pos=-1;
}
}bit[maxn];
struct Edge{
int u,v,d;
}edge[maxn<<2];
bool cmpedge(Edge a,Edge b)
{
return a.d<b.d;
}
int tot;
int n;
int F[maxn];
int find(int x)
{
if(F[x]==-1) return x;
else return F[x]=find(F[x]);
}
void addedge(int u,int v,int d)
{
edge[tot].u=u;
edge[tot].v=v;
edge[tot++].d=d;
}
int lowbit(int x){return x&-x;}
void update(int i,int val,int pos)
{
while(i>0)
{
if(val<bit[i].min_val)
{
bit[i].min_val=val;
bit[i].pos=pos;
}
i-=lowbit(i);
}
}
int ask(int i,int m)
{
int min_val=INF,pos=-1;
while(i<=m)
{
if(bit[i].min_val<min_val)
{
min_val=bit[i].min_val;
pos=bit[i].pos;
}
i+=lowbit(i);
}
return pos;
}
int dist(point a,point b)
{
return abs(a.x-b.x)+abs(a.y-b.y);
}
void Manhattan_minimum_spanning_tree(int n,point p[])
{
int a[maxn],b[maxn];
tot=0;
for(int dir=0;dir<4;dir++)
{
if(dir==1||dir==3)
{
for(int i=0;i<n;i++)
swap(p[i].x,p[i].y);
}
else if(dir==2)
{
for(int i=0;i<n;i++)
p[i].x=-p[i].x;
}
sort(p,p+n,cmp);
for(int i=0;i<n;i++)
a[i]=b[i]=p[i].y-p[i].x;
sort(b,b+n);
int m=unique(b,b+n)-b;
for(int i=1;i<=m;i++)
bit[i].init();
for(int i=n-1;i>=0;i--)
{
int pos=lower_bound(b,b+m,a[i])-b+1;
int ans=ask(pos,m);
if(ans!=-1)
addedge(p[i].id,p[ans].id,dist(p[i],p[ans]));
update(pos,p[i].x+p[i].y,i);
}
}
}
ll solve(int num)
{
Manhattan_minimum_spanning_tree(n,p);
memset(F,-1,sizeof F);
sort(edge,edge+tot,cmpedge);
ll ans=0;
for(int i=0;i<tot;i++)
{
int u=edge[i].u;
int v=edge[i].v;
int t1=find(u),t2=find(v);
if(t1!=t2)
{
F[t1]=t2;
num--;
if(!num)
return edge[i].d;
}
}
return ans;
}
int k;
int main()
{
//freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n,&k))
{
for(int i=0;i<n;i++)
{
scanf("%d%d",&p[i].x,&p[i].y);
p[i].id=i;
}
ll ans=solve(n-k);
printf("%lld\n",ans);
}
return 0;
}