BZOJ 1604 [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居

来源:互联网 发布:c语言 buffer 编辑:程序博客网 时间:2024/04/29 14:23

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行输入NC,之后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.



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.

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;}


0 0
原创粉丝点击