Problem Description
给你n个点(二维),让你求所有点 到最远点 和最近点 的距离差最小
思路:
自身点不算。
求个距离该点,最近距离。和 距离该点,最远距离即可。
这里的距离指的是 曼哈顿距离
#include<bits/stdc++.h>
using namespace std;
const int MAX = 500010;
const int inf = 0x3f3f3f3f;
const int DIM = 2;
struct node
{
int l, r;
int d[DIM], maxn[DIM], minn[DIM];
inline void maintain()//初始化
{
l = r = 0;
for(int i = 0; i < DIM; i++)
maxn[i] = minn[i] = d[i];
}
}tree[MAX];
int D;
bool operator < (const node &a, const node &b)//重载,从小到大
{
return a.d[D] < b.d[D];
}
inline void Merge(int mid)//归并,向上更新
{
int son[2] = {tree[mid].l, tree[mid].r};
for(int i = 0; i < 2; i++)
{
if(!son[i]) continue;
for(int j = 0; j < DIM; j++)
{
tree[mid].maxn[j] = max(tree[mid].maxn[j], tree[son[i]].maxn[j]);
tree[mid].minn[j] = min(tree[mid].minn[j], tree[son[i]].minn[j]);
}
}
}
int build(int l, int r, int now)//建树
{
int mid = (l+r) >> 1;
D = now;
nth_element(tree+l, tree+mid, tree+r+1);//对于now维,以mid为中间,左边都是比它小,右边都是比它大。
tree[mid].maintain();//初始化
if(l < mid) tree[mid].l = build(l, mid-1, (now+1)%DIM);
if(r > mid) tree[mid].r = build(mid+1, r, (now+1)%DIM);
Merge(mid);
return mid;
}
int ans1, ans2;
int partionMin(int o, int k)//求最小可能值
{
int red = 0;
for(int i = 0; i < DIM; i++)
{
if(tree[k].d[i] > tree[o].maxn[i]) red += tree[k].d[i] - tree[o].maxn[i];
if(tree[k].d[i] < tree[o].minn[i]) red += tree[o].minn[i] - tree[k].d[i];
}
return red;
}
int partionMax(int o, int k)//求最大可能值
{
int red = 0;
for(int i = 0; i < DIM; i++)
{
red += max(abs(tree[k].d[i] - tree[o].maxn[i]), abs(tree[k].d[i] - tree[o].minn[i]));
}
return red;
}
void queryMin(int o, int k)//求最小距离
{
int dm = abs(tree[k].d[0] - tree[o].d[0]) + abs(tree[k].d[1] - tree[o].d[1]);
if(o == k) dm = inf;//自身点不算。
if(ans1 > dm) ans1 = dm;
int dl = tree[o].l ? partionMin(tree[o].l, k) : inf;
int dr = tree[o].r ? partionMin(tree[o].r, k) : inf;
if(dl < dr)
{
if(dl < ans1) queryMin(tree[o].l, k);
if(dr < ans1) queryMin(tree[o].r, k);
}
else
{
if(dr < ans1) queryMin(tree[o].r, k);
if(dl < ans1) queryMin(tree[o].l, k);
}
}
void queryMax(int o, int k)//求最大距离
{
int dm = abs(tree[k].d[0] - tree[o].d[0]) + abs(tree[k].d[1] - tree[o].d[1]);
if(ans2 < dm) ans2 = dm;
int dl = tree[o].l ? partionMax(tree[o].l, k) : 0;
int dr = tree[o].r ? partionMax(tree[o].r, k) : 0;
if(dl > dr)
{
if(dl > ans2) queryMax(tree[o].l, k);
if(dr > ans2) queryMax(tree[o].r, k);
}
else
{
if(dr > ans2) queryMax(tree[o].r, k);
if(dl > ans2) queryMax(tree[o].l, k);
}
}
int main()
{
int n, i, j;
while(~scanf("%d", &n))
{
for(i = 1; i <= n; i++)
for(j = 0; j < DIM; j++)
scanf("%d", &tree[i].d[j]);
int root = build(1, n, 0);
int Ans;
for(i = 1; i <= n; i++)
{
ans1 = inf;
ans2 = 0;
queryMin(root, i);
queryMax(root, i);
Ans = min(Ans, ans2 - ans1);
}
printf("%d\n", Ans);
}
}