題目連結:http://www.lydsy.com/JudgeOnline/problem.php?id=1604
題意:
平面直角座標系中,有n個點(n <= 100000,座標範圍10^9)。
給定r,當兩個點的曼哈頓距離<=r時,認為這兩個點在同一個“群”中。
問你共有多少個群,以及點的數量最多的群有多少個點。
題解:
本題的核心在於:如何列舉一個點周圍滿足“曼哈頓距離<=r”的點。
由於 曼哈頓距離 = |x1 - x2| + |y1 - y2|。
x和y相互影響,不能單純按x或y排序,列舉所有點總複雜度為O(N^2)。
所以要用到曼哈頓距離的另一種形式:
設X = x + y , Y = x - y
d(曼哈頓距離) = max(|X1-X2|, |Y1-Y2|)
將每個點的X = x + y,Y = x - y,這就將X與Y的關係分離開了。
將所有點按X排序。
當前考慮到點i。
用一個佇列(X升序),保證佇列中的所有X滿足要求,否則不斷刪去隊首。
用一個multiset(Y升序),找到i的前驅pre和後繼suc,如果i與pre(或suc)的Y滿足要求,則合併(並查集)。
最後統計一下每個群就好了。
AC Code:
1 // |x1-x2| + |y1-y2| 2 // | (x1+y1) - (x2+y2) | 3 // | (x1-y1) - (x2-y2) | 4 // X = x + y 5 // Y = x - y 6 // d = max(|X1-X2|, |Y1-Y2|) <= r 7 #include <iostream> 8 #include <stdio.h> 9 #include <string.h> 10 #include <algorithm> 11 #include <set> 12 #define MAX_N 100005 13 #define INF 100000000 14 15 using namespace std; 16 17 struct Coor 18 { 19 int x; 20 int y; 21 int idx; 22 Coor(int _x,int _y,int _idx) 23 { 24 x=_x; 25 y=_y; 26 idx=_idx; 27 } 28 Coor(){} 29 friend bool operator < (const Coor &a,const Coor &b) 30 { 31 return a.y!=b.y?a.y<b.y:a.idx<b.idx; 32 } 33 }; 34 35 int n,r; 36 int ans=1; 37 int counter=0; 38 int head=0; 39 int par[MAX_N]; 40 int cnt[MAX_N]; 41 Coor c[MAX_N]; 42 multiset<Coor> mst; 43 44 inline bool cmp_x(const Coor &a,const Coor &b) 45 { 46 return a.x<b.x; 47 } 48 49 void init_union_find() 50 { 51 for(int i=0;i<n;i++) 52 { 53 par[i]=i; 54 } 55 } 56 57 int find(int x) 58 { 59 return par[x]==x?x:par[x]=find(par[x]); 60 } 61 62 void unite(int x,int y) 63 { 64 int px=find(x); 65 int py=find(y); 66 if(px==py) return; 67 par[px]=py; 68 } 69 70 void read() 71 { 72 cin>>n>>r; 73 int a,b; 74 for(int i=0;i<n;i++) 75 { 76 cin>>a>>b; 77 c[i].x=a+b; 78 c[i].y=a-b; 79 c[i].idx=i; 80 } 81 } 82 83 void solve() 84 { 85 init_union_find(); 86 sort(c,c+n,cmp_x); 87 mst.insert(Coor(0,INF,0)); 88 mst.insert(Coor(0,-INF,0)); 89 mst.insert(c[head]); 90 for(int i=1;i<n;i++) 91 { 92 while(c[i].x-c[head].x>r) 93 { 94 mst.erase(c[head]); 95 head++; 96 } 97 multiset<Coor>::iterator it=mst.lower_bound(c[i]); 98 Coor suc=*it; 99 Coor pre=*--it; 100 if(c[i].y-pre.y<=r) unite(pre.idx,c[i].idx); 101 if(suc.y-c[i].y<=r) unite(suc.idx,c[i].idx); 102 mst.insert(c[i]); 103 } 104 memset(cnt,0,sizeof(cnt)); 105 for(int i=0;i<n;i++) 106 { 107 int p=find(i); 108 if(cnt[p]==0) counter++; 109 cnt[p]++; 110 ans=max(ans,cnt[p]); 111 } 112 } 113 114 void print() 115 { 116 cout<<counter<<" "<<ans<<endl; 117 } 118 119 int main() 120 { 121 read(); 122 solve(); 123 print(); 124 }