bzoj1604 牛的邻居 STL
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
1 1
3 3
2 2
10 10
Sample Output
2 3
【题解】
本题需要求曼哈顿距离,并且在寻找邻居的时候只要找距离自己最近的奶牛看看与它是否属于同一个群。很容易想到使用平衡树求前驱和后继,但是求曼哈顿距离的公式|X1-X2|+|Y1-Y2|很难维护。
所以我们要对数据进行处理,讲每个点变为(x+y,x-y),这样曼哈顿距离就是max(|X1-X2|,|Y1-Y2|)。每次比较只要比较两个点的一个值就可以了。
所以我们用一个队列维护x,用一个平衡树(或者multiset)去维护y。找到合法的就用并查集将两个合在一起。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define maxn 100005 4 #define ll long long 5 int f[maxn],tot[maxn]; 6 int n,m,ans,mx; 7 ll c; 8 struct node{ 9 ll x,y;int id; 10 }a[maxn]; 11 inline int read(){ 12 int x,f;char ch=getchar(); 13 while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 multiset<node> b; 18 multiset<node>:: iterator it; 19 bool cmp(node a,node b){ 20 return a.x<b.x; 21 } 22 bool operator<(node a,node b){return a.y<b.y;} 23 int find(int x){ 24 if(f[x]!=x)return find(f[x]); 25 else return x; 26 } 27 void work(int x,int y){//将两个群合并在一起 28 int p=find(x),q=find(y); 29 if(p!=q){ 30 tot[p]+=tot[q];tot[q]=0;ans--; 31 f[q]=p; 32 } 33 } 34 void solve(){ 35 node k;int i,he=1; 36 sort(a+1,a+n+1,cmp);b.insert(a[1]); 37 k.x=0;k.y=1e10;k.id=0;b.insert(k); 38 k.x=0;k.y=-1e10;k.id=0;b.insert(k); 39 for(i=2;i<=n;i++){ 40 while(a[i].x-a[he].x>c)b.erase(b.find(a[he])),++he;//判断x是否合法 41 it=b.lower_bound(a[i]); 42 k=*it; 43 if(k.y-a[i].y<=c)work(k.id,a[i].id); 44 k=*--it; 45 if(a[i].y-k.y<=c)work(k.id,a[i].id); 46 b.insert(a[i]); 47 } 48 } 49 int main(){ 50 scanf("%d%d",&n,&c); 51 int kx,ky; 52 ans=n;//ans是群数,tot是每个群里牛的数量 53 for(int i=1;i<=n;i++){ 54 scanf("%d%d",&kx,&ky); 55 f[i]=i;tot[i]=1; 56 a[i].x=kx+ky; 57 a[i].y=kx-ky; 58 a[i].id=i; 59 } 60 solve(); 61 for(int i=1;i<=n;i++)mx=max(tot[i],mx); 62 printf("%d %d",ans,mx); 63 return 0; 64 }