第1行输入N和C,之后N行每行输入一只奶牛的坐标.
仅一行,先输出牛群数,再输出最大牛群里的牛数,用空格隔开.
Gold
【思路】
Set+并查集
曼哈顿距离分为以下情况
X-x+Y-y -> (X+Y)-(x+y)
X-x+y-Y -> (X-Y)-(x-y)
x-X+Y-y -> -( (X-Y)-(x-y) )
x-X+y-Y -> -( (X+Y)-(x+y) )
这四种情况,我们可以发现,答案就是
max( |(X+Y)-(x+y)|, |(X-Y)-(x-y)| )
于是把每个点变为(x+y,x-y) 并将x从小到大排序
维护一个队列使得front~i区间x坐标的差均小于c
用set维护队列元素中的y,如果i在set中的前驱或后继与i的y之差小于c则合并集合。
【代码】
1 #include<set> 2 #include<cstdio> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 typedef long long LL; 8 const int N = 1e5+10; 9 const int INF = 1e9+1e9+7; 10 struct Node{ 11 int x,y; 12 bool operator < (const Node& rhs) const{ 13 return x<rhs.x; 14 } 15 }a[N]; 16 int n,c,p[N],sum[N],ans,mx; 17 multiset<Node> S; 18 multiset<Node> ::iterator it; 19 20 int ifind(int u) { 21 return u==p[u]? u:p[u]=ifind(p[u]); 22 } 23 void unit(int x,int y) { 24 x=ifind(x),y=ifind(y); if(x!=y) p[x]=y; 25 } 26 27 void read(int& x) { 28 char c=getchar(); int f=1; x=0; 29 while(!isdigit(c)){if(c=='-')f=-1; c=getchar();} 30 while(isdigit(c)) x=x*10+c-'0',c=getchar(); 31 x*=f; 32 } 33 int main() { 34 read(n),read(c); 35 for(int i=1;i<=n;i++) p[i]=i; 36 int x,y; 37 for(int i=1;i<=n;i++) { 38 read(x),read(y); 39 a[i].x=x+y,a[i].y=x-y; 40 } 41 sort(a+1,a+n+1); 42 S.insert((Node){INF,0}),S.insert((Node){-INF,0}); 43 int front=1; 44 for(int i=1;i<=n;i++) { 45 while(a[i].x-a[front].x>c) { 46 S.erase(S.lower_bound((Node){a[front].y,front})); 47 ++front; 48 } 49 it=S.lower_bound((Node){a[i].y,i}); 50 Node r=*it,l=*(--it); 51 if((LL)r.x-(LL)a[i].y<=c) unit(r.y,i); 52 if((LL)a[i].y-(LL)l.x<=c) unit(l.y,i); 53 S.insert((Node){a[i].y,i}); 54 } 55 for(int i=1;i<=n;i++) { 56 sum[ifind(i)]++; 57 if(sum[ifind(i)]==1) ans++; 58 } 59 for(int i=1;i<=n;i++) mx=max(mx,sum[i]); 60 printf("%d %d",ans,mx); 61 return 0; 62 }