P2906 [USACO08OPEN]Cow Neighborhoods G 切比雪夫距离 + 并查集 + set
傳送門
考慮將曼哈頓距離轉換成切比雪夫距離,這樣問題就變成了max(∣x1?x2∣,∣y1?y2∣)≤dmax(|x_1-x_2|,|y_1-y_2|)\le dmax(∣x1??x2?∣,∣y1??y2?∣)≤d,這個式子就很好看了,我們首先按照(x,y)(x,y)(x,y)排序,讓后我們雙指針控制∣xr?xl∣<=d|x_r-x_l|<=d∣xr??xl?∣<=d,用multisetmultisetmultiset維護[l,r][l,r][l,r]內的yyy坐標,一開始比較暴力的想法就是找到[yr?d,yr+d][y_r-d,y_r+d][yr??d,yr?+d]區間內的數,讓后用并查集維護,但是這樣顯然是可以卡成O(n2)O(n^2)O(n2)的,仔細想一下,有必要遍歷所有點嗎?并沒有,假設我們二分找到了≥yr?d\ge y_r-d≥yr??d的第一個位置pospospos,那么不難發現[pos,pos+d][pos,pos+d][pos,pos+d]對應的數都已經合并到一個集合中了,并沒有必要去遍歷,所以我們只需要找yr?d,yr+1y_r-d,y_r+1yr??d,yr?+1對應在multisetmultisetmultiset里面的位置即可。
復雜度O(nlogn)O(nlogn)O(nlogn)
#include<bits/stdc++.h> #define X first #define Y second #define L (u<<1) #define R (u<<1|1) #define Mid (tr[u].l+tr[u].r>>1) #define pb push_back using namespace std;const int N=1000010,INF=0x3f3f3f3f,mod=1e9+7; typedef long long LL; typedef pair<int,int> PII;int n,d; int p[N],se[N]; struct Point {int x,y;bool operator < (const Point &W) const {if(x!=W.x) return x<W.x;else return y<W.y;} }a[N];int find(int x) {return x==p[x]? x:p[x]=find(p[x]); }void solve() {multiset<PII>s;scanf("%d%d",&n,&d);for(int i=1;i<=n;i++) {int x,y;scanf("%d%d",&x,&y);p[i]=i;a[i].x=x+y; a[i].y=x-y;}sort(a+1,a+1+n);for(int l=1,r=1;r<=n;r++) {s.insert({a[r].y,r});while(a[r].x-a[l].x>d) {s.erase(s.find({a[l].y,l}));l++;}int y=a[r].y;auto it=s.lower_bound({y-d,0});if(it!=s.end()) {PII u=*it;if(u.X<=y+d) {p[find(r)]=find(u.Y);it=s.lower_bound({y+1,0});if(it!=s.end()) {u=*it;if(u.X<=y+d) {p[find(r)]=find(u.Y);}}}}}int ans,mx;ans=0; mx=0;for(int i=1;i<=n;i++) {if(se[find(i)]==0) ans++;se[find(i)]++;mx=max(mx,se[find(i)]);}printf("%d %d\n",ans,mx); }int main() {int _=1;while(_--) {solve();}return 0; } /**/總結
以上是生活随笔為你收集整理的P2906 [USACO08OPEN]Cow Neighborhoods G 切比雪夫距离 + 并查集 + set的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 五皮风的功效与作用
- 下一篇: 2018-2019 ACM-ICPC,