bzoj 1604 奶牛的邻居
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.
思路:我们把点对坐标转化为(x+y,x-y),那么曼哈顿距离就转化为了max(|x1-x2|,|y1-y2|); 我们把点按照x坐标排序,然后维护一个队列,队列中元素的x坐标差的绝对值是不大于C的。然后用平衡树(或者multiset),维护y坐标,每次查找y坐标前驱后继,并检验y坐标差值是否大于C,如果不大于,就可以用并查集连接当前点和其y坐标前驱后继,最后通过统计并查集数量和每个并查集大小来得到答案。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define rep(i,a,b) for(R i=a;i<=b;i++) 5 #define Rep(i,a,b) for(R i=a;i>=b;i--) 6 #define ms(i,a) memset(a,i,sizeof(a)) 7 template<class T>void read(T &x){ 8 x=0; char c=0; 9 while (!isdigit(c)) c=getchar(); 10 while (isdigit(c)) x=x*10+(c^48),c=getchar(); 11 } 12 int const N=100003; 13 struct node{ 14 int vy,id; 15 bool operator < (const node & rhs) const{ 16 if(vy!=rhs.vy) return vy<rhs.vy; 17 else return id<rhs.id; 18 } 19 }; 20 struct cow{ 21 int x,y; 22 bool operator< (const cow &rhs) const{ 23 return x<rhs.x; 24 } 25 }a[N]; 26 int n,c,f[N],sz[N],vis[N],ans; 27 set<node> s; 28 set<node> :: iterator p; 29 int gf(int x){return x==f[x]? x:f[x]=gf(f[x]);} 30 void un(int x,int y){ 31 int fx=gf(x),fy=gf(y); 32 if(fx==fy) return ; 33 f[fx]=fy; sz[fy]+=sz[fx];ans--; 34 } 35 int main(){ 36 read(n); read(c); ans=n; 37 rep(i,1,n){ 38 int x,y; read(x); read(y); 39 a[i].x=x+y;a[i].y=x-y; 40 } 41 sort(a+1,a+n+1); 42 rep(i,1,n) f[i]=i,sz[i]=1; 43 int k=1; 44 rep(i,1,n){ 45 while (a[i].x-a[k].x>c){ 46 node t=(node){a[k].y,k}; k++; s.erase(t); 47 } 48 node t;t.vy=a[i].y;t.id=i; 49 p=s.lower_bound(t); 50 if(p!=s.end()){ 51 if(p->vy-a[i].y<=c) un(i,p->id); 52 if(p!=s.begin()){ 53 --p; if(a[i].y-p->vy<=c) un(i,p->id); 54 } 55 }else if(s.size()){ 56 p=--s.end(); 57 if(a[i].y-p->vy<=c) un(i,p->id); 58 } 59 s.insert(t); 60 } 61 int maxs=0; 62 rep(i,1,n) { 63 int fx=gf(i); 64 if(vis[fx]) continue; 65 vis[fx]=1; 66 maxs=max(maxs,sz[fx]); 67 } 68 cout<<ans<<" "<<maxs<<endl; 69 return 0; 70 }