Description
了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000)只奶牛,你会发现她们已经结成了几个“群”.每只奶牛在吃草的时候有一个独一无二的位置坐标Xi,Yi(l≤Xi,Yi≤[1..10^9];Xi,Yi∈整数.当满足下列两个条件之一,两只奶牛i和j是属于同一个群的:
1.两只奶牛的曼哈顿距离不超过C(1≤C≤10^9),即lXi - xil+IYi - Yil≤C.
2.两只奶牛有共同的邻居.即,存在一只奶牛k,使i与k,j与k均同属一个群.
给出奶牛们的位置,请计算草原上有多少个牛群,以及最大的牛群里有多少奶牛
Input
第1行输入N和C,之后N行每行输入一只奶牛的坐标.
Output
仅一行,先输出牛群数,再输出最大牛群里的牛数,用空格隔开.
Sample Input
4 2
1 1
3 3
2 2
10 10
* Line 1: A single line with a two space-separated integers: the
number of cow neighborhoods and the size of the largest cow
neighborhood.
1 1
3 3
2 2
10 10
* Line 1: A single line with a two space-separated integers: the
number of cow neighborhoods and the size of the largest cow
neighborhood.
Sample Output
2 3
OUTPUT DETAILS:
There are 2 neighborhoods, one formed by the first three cows and
the other being the last cow. The largest neighborhood therefore
has size 3.
OUTPUT DETAILS:
There are 2 neighborhoods, one formed by the first three cows and
the other being the last cow. The largest neighborhood therefore
has size 3.
HINT
Source
真是一道神题。
题目上这个距离叫曼哈顿距离,还有一个距离叫切比雪夫距离(不懂找度娘)。
最大的困难就是坐标是二维的,枚举太浪费时间了。
如果将点坐标转换(x+y,x-y),那么横纵坐标之差的绝对值就是曼哈顿距离了。
如果将点坐标按x排序,维护一个队列x之差小于等于c,
每次挑y的前驱和后继,判断,如果满足,就加入并查集,每次只需要判断最近的两点即可。
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<set>
using namespace std;
const int N=100005;
const long long inf=10000000000LL;
int n,ans,mx,f[N],tot[N];
long long c;
struct node
{
long long x,y;
int id;
}a[N];
multiset<node>st;
bool operator < (node c,node d)
{
return c.y<d.y;
}
bool cmp(node c,node d)
{
if(c.x==d.x)
return c.y<d.y;
return c.x<d.x;
}
int fnd(int x)
{
return x==f[x]?x:f[x]=fnd(f[x]);
}
void un(int x,int y)
{
int fx=fnd(x),fy=fnd(y);
if(fx!=fy)
{
ans--;
f[fx]=fy;
}
}
int main()
{
scanf("%d%lld",&n,&c);
ans=n;
for(int i=1;i<=n;i++)
f[i]=i;
for(int i=1;i<=n;i++)
{
long long x,y;
scanf("%lld%lld",&x,&y);
a[i].x=x+y;
a[i].y=x-y;
a[i].id=i;
}
sort(a+1,a+n+1,cmp);
st.insert((node){0,inf,0}),st.insert((node){0,-inf,0});
st.insert(a[1]);
int now=1;
for(int i=2;i<=n;i++)
{
while(a[i].x-a[now].x>c)
{
st.erase(st.find(a[now]));
now++;
}
multiset<node>::iterator it=st.lower_bound(a[i]);
node r=*it,l=*--it;
if(a[i].y-l.y<=c)
un(a[i].id,l.id);
if(r.y-a[i].y<=c)
un(a[i].id,r.id);
st.insert(a[i]);
}
for(int i=1;i<=n;i++)
tot[fnd(i)]++;
for(int i=1;i<=n;i++)
mx=max(mx,tot[i]);
printf("%d %d\n",ans,mx);
return 0;
}