【題解】[JOISC 2021 Day1]道路の建設案
阿新 • • 發佈:2021-10-04
這應該是 JOISC2021 最簡單的一題了。
求前 $k $ 大的曼哈頓距離,先考慮求第 \(k\) 大的距離。
第 \(k\) 大的距離,比較套路的做法是二分答案,然後計算距離 \(\le dis\) 的點對數。
曼哈頓距離不好求,考慮轉化為切比雪夫距離,原來的點 \((x,y)\to (x+y,x-y)\) 。
那麼這就是一個經典的二維數點問題。
同時我們不需要真正數有多少點對,點對數 \(\ge k\) 時直接返回即可。
所以具體操作是對所有點按 \(x\) 座標排序,用佇列維護 \(x\) 座標在 \(dis\) 範圍內的點,同時用 set
維護佇列中的點的 \(y\) 座標。
值域為 \(S\)
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) #define pre(i,a,b) for(int i=a;i>=b;i--) #define N 250005 #define inf 0x3f3f3f3f3f3f3f3fLL #define int long long using namespace std; int n,k; typedef pair<int,int> Pr; #define X first #define Y second set<Pr>s;queue<Pr>q;Pr a[N]; int ans[N],T; bool check(int dis){ T=0;s.clear(); while(!q.empty())q.pop(); rep(i,1,n){ while(!q.empty()&&q.front().X+dis<a[i].X)s.erase(make_pair(q.front().Y,q.front().X)),q.pop(); set<Pr>::iterator it=s.lower_bound(make_pair(a[i].Y-dis,-inf)); while(it!=s.end()&&(*it).X<=dis+a[i].Y){ ans[++T]=max(abs((*it).X-a[i].Y),a[i].X-(*it).Y); it++;if(T>=k)return true; } s.insert(make_pair(a[i].Y,a[i].X));q.push(make_pair(a[i].X,a[i].Y)); } return false; } signed main(){ scanf("%lld%lld",&n,&k); rep(i,1,n){ int x,y;scanf("%lld%lld",&x,&y); a[i].X=x+y;a[i].Y=x-y; } sort(a+1,a+n+1);puts("No Copy"); int l=1,r=4000000000,ed=0; while(l<=r){ int mid=(0LL+l+r)>>1; if(check(mid))ed=mid,r=mid-1; else l=mid+1; } check(ed-1); sort(ans+1,ans+T+1); rep(i,1,T)printf("%lld\n",ans[i]); rep(i,1,k-T)printf("%lld\n",ed); return 0; }