BZOJ 1604: [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居
题目
1604: [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居
Time Limit: 5 Sec Memory Limit: 64 MBDescription
了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的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.
题解
这题很明显就是再考并查集!【真的吗,你看下数据范围!】关于曼哈顿距离的技巧,将每个点变成(x+y,x-y)这样两个点之间的曼哈顿距离就是|x1-x2|+|y1-y2|,这样就可以维护一个平衡树,根据前驱和后继上面的节点来维护并查集求得答案了!
代码
/*Author:WNJXYK*/ #include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<queue> #include<set> #include<map> using namespace std; #define LL long long #define Inf 2147483647 #define InfL 10000000000LL inline void swap(int &x,int &y){int tmp=x;x=y;y=tmp;} inline void swap(LL &x,LL &y){LL tmp=x;x=y;y=tmp;} inline int remin(int a,int b){if (a<b) return a;return b;} inline int remax(int a,int b){if (a>b) return a;return b;} inline LL remin(LL a,LL b){if (a<b) return a;return b;} inline LL remax(LL a,LL b){if (a>b) return a;return b;} inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,c,ans,mx; int fa[100005],tot[100005]; struct data{LL x,y;int id;}a[100005]; multiset <data> b; set <data>::iterator it; inline bool operator<(data a,data b){ return a.y<b.y; } inline bool cmpx(data a,data b){ return a.x<b.x; } int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]); } inline void un(int x,int y){ int p=find(x),q=find(y); if(p!=q){ fa[p]=q; ans--; } } void solve(){ b.insert((data){0,InfL,0});b.insert((data){0,-InfL,0}); int now=1;b.insert(a[1]); for(int i=2;i<=n;i++){ while(a[i].x-a[now].x>c){ b.erase(b.find(a[now])); now++; } it=b.lower_bound(a[i]); data 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); b.insert(a[i]); } } int main(){ n=read();c=read();ans=n; for(int i=1;i<=n;i++)fa[i]=i; for(int i=1;i<=n;i++){ int t1=read(),t2=read(); a[i].x=t1+t2,a[i].y=t1-t2;a[i].id=i; } sort(a+1,a+n+1,cmpx); solve(); for(int i=1;i<=n;i++) tot[find(i)]++; for(int i=1;i<=n;i++) mx=max(mx,tot[i]); printf("%d %d\n",ans,mx); return 0; }