曼哈頓距離最小生成樹: https://www.cnblogs.com/xzxl/p/7237246.html
這道題顯然是求曼哈頓距離的最大生成樹,和求最小生成樹一樣,用個樹狀數組維護最值,加邊後跑kruskal,不同的是最大生成樹需要枚舉8個方向的最大值。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include<queue>
using namespace std;
struct P{
int x,y,id;
}A[100010];
struct Q{
int a,b,c;
}C[2000010];
int T[100010],pos[100010],ha[100010],h,cnt=0;
int cmp(P a,P b){
if(a.x==b.x) return a.y<b.y;
return a.x<b.x;
}
int cmp1(Q a,Q b){
return a.c>b.c;
}
int id(int x){
return lower_bound(ha+1,ha+1+h,x)-ha;
}
void add(int x,int v,int k){
for(;x<=1e5;x+=x&-x){
if(T[x]<v){
T[x]=v;
pos[x]=k;
}
}
}
int qmax(int x){
int ans=0,ma=-2000000009;
for(;x;x-=x&-x){
if(ma<T[x]){
ma=T[x];
ans=pos[x];
}
}
return ans;
}
void build(int n){
int i,j,k,x;
for(j=1;j<=8;j++){
for(i=1;i<=n;i++){
if(j%2==0) swap(A[i].x,A[i].y);
else A[i].x*=-1;
}
sort(A+1,A+1+n,cmp);
for(i=1;i<=n;i++) ha[i]=A[i].x-A[i].y;
sort(ha+1,ha+1+n);
h=unique(ha+1,ha+1+n)-ha-1;
for(i=0;i<=1e5;i++){
T[i]=-2000000009;
pos[i]=0;
}
for(i=n;i;i--){
k=id(A[i].x-A[i].y);
x=qmax(k);
if(x){
C[++cnt].a=A[i].id;
C[cnt].b=A[x].id;
C[cnt].c=abs(A[x].x-A[i].x)+abs(A[x].y-A[i].y);
}
add(k,A[i].x+A[i].y,i);
}
}
}
int p[100010];
int f(int x){
if(x==p[x]) return x;
p[x]=f(p[x]);
return p[x];
}
int main(){
int a,b,i,n;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d%d",&A[i].x,&A[i].y);
A[i].id=p[i]=i;
}
build(n);
sort(C+1,C+1+cnt,cmp1);
int ans=0;
for(i=1;i<=cnt;i++){
a=f(C[i].a);
b=f(C[i].b);
if(a!=b){
p[a]=b;
ans=C[i].c;
}
}
printf("%d\n",ans);
}