平面点对问题,切比雪夫距离

题目描述

给定平面的n个点(n<=1e5),所有坐标的绝对值在50000以内,现在问你有多少对点之间的距离不小于d。这里距离描述为两点的曼哈顿距离,即dist=|xi-xj|+|yi-yj|。

思路

如果将平面上小于等于d的曼哈顿距离画出来,会是一个菱形

平面点对问题,切比雪夫距离_第1张图片

 

切比雪夫距离:平面上两个点(x1,y1)(x2,y2)的切比雪夫距离为max⁡(∣x1−x2∣,∣y1−y2∣),其中∣x∣为x的绝对值

将曼哈顿距离转换为切比雪夫距离后,我们发现切比雪夫距离固定的点呈正方形

平面点对问题,切比雪夫距离_第2张图片

这样我们就可以先将数据离线,按照yy的大小对点进行排序,然后用树状数组维护长度为dd的正方形区域内点的个数即可,这部分代码相对就比较模板了

#include 
#define int long long
using namespace std;

const int maxn=1e6+10;
int n,d,fk;
const int fix=5e5+10;
struct Point{
    int x,y;
    bool operator < (const Point &rhs)const{
        return x0){
        res+=c[x];
        x-=lowbit(x);
    }
    return res;
}
signed main(){
    scanf("%lld%lld%lld",&n,&d,&fk);
    d--;
    for(int i=1;i<=n;i++){
        int x,y;
        scanf("%lld%lld",&x,&y);
        //转化为切比雪夫坐标
        node[i].x=x+y;
        node[i].y=x-y+fix;
    }
    sort(node+1,node+n+1);
    int ans=0;
    for(int i=1,j=1;i<=n;i++){
        while(jd){
            add(node[j].y,-1);
            j++;
        }
        ans+=Sum(node[i].y+d)-Sum(node[i].y-d-1);
        add(node[i].y,1);
    }
    ans=n*(n-1)/2-ans;
    printf("%lld\n",ans);
    return 0;
}

 

你可能感兴趣的:(思维题,线段树)