[USACO08OPEN]牛的街区Cow Neighborhoods
题目描述:
题解:
技巧题。
曼哈顿距离:$|x1-x2|+|y1-y2|$
切比雪夫距离:$\max(|x1-x2|,|y1-y2|)$
曼哈顿距离转切比雪夫距离:$(x,y)->(x+y,x-y)$
所以……排完序拿stl::set模拟就好了。
代码:
#include<set> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N = 100050; template<typename T> inline void read(T&x) { T f = 1,c = 0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();} x = f*c; } int n,c,ff[N],siz[N]; int findff(int x){return x==ff[x]?x:ff[x]=findff(ff[x]);} void merge(int x,int y) { x = findff(x),y = findff(y); if(x!=y)ff[x] = y,siz[y]+=siz[x]; } struct Point { ll x,y;int id; Point(){} Point(ll x,ll y):x(x),y(y){} bool operator < (const Point&a)const{return x!=a.x?x<a.x:y<a.y;} }p[N]; bool cmp(Point a,Point b){return a.y!=b.y?a.y<b.y:a.x<b.x;} set<Point>tr; int main() { read(n),read(c);ll x,y; for(int i=1;i<=n;i++) { read(x),read(y); p[i] = Point(x+y,x-y); } sort(p+1,p+1+n,cmp); for(int i=1;i<=n;i++) siz[i]=1,ff[i]=i,p[i].id=i; set<Point>::iterator it;Point now; for(int i=1,j=1;i<=n;i++) { while(p[i].y-p[j].y>c)tr.erase(p[j]),j++; it = tr.lower_bound(p[i]); if(it!=tr.end()) { now=(*it); if(now.x-p[i].x<=c)merge(now.id,i); } if(it!=tr.begin()) { it--;now=(*it); if(p[i].x-now.x<=c)merge(now.id,i); } tr.insert(p[i]); } int ans1 = 0,ans2 = -1; for(int i=1;i<=n;i++) if(findff(i)==i)ans1++,ans2=max(ans2,siz[i]); printf("%d %d\n",ans1,ans2); return 0; }