牛客挑战赛34 - D 拉普兰德的愿望(曼哈顿距离转切比雪夫距离)

链接:牛客挑战赛34 - D 拉普兰德的愿望

题意:

给出平面上 N ( 100 , 000 ) N(\le100,000) 个点,坐标绝对值不超过 L ( 50 , 000 ) L(\le50,000) ,求曼哈顿距离不小于 d ( 10 , 000 , 000 ) d(\le10,000,000) 的点对共有多少?

对于点对 ( x 1 , y 1 ) (x_1,y_1) ( x 2 , y 2 ) (x_2,y_2) ,其曼哈顿距离即为 x 1 x 2 + y 1 y 2 |x_1-x_2|+|y_1-y_2|



分析:

参考Blog:传送门

曼哈顿距离 x 1 x 2 + y 1 y 2 |x_1-x_2|+|y_1-y_2|
切比雪夫距离 max ( x 1 x 2 , y 1 y 2 ) \max(|x_1−x_2|,|y_1−y_2|)

  • 将一个点 ( x , y ) (x,y) 的坐标变为 ( x + y , x y ) (x+y,x−y) 后,原坐标系中的曼哈顿距离 = = 新坐标系中的切比雪夫距离
  • 将一个点 ( x , y ) (x,y) 的坐标变为 ( x + y 2 , x y 2 ) (\frac{x+y}{2},\frac{x−y}{2}) 后,原坐标系中的切比雪夫距离 = = 新坐标系中的曼哈顿距离

曼哈顿距离中,距离原点为 1 1 ,构成下图:
在这里插入图片描述
而转化为切比雪夫距离后,距离源点为 1 1 ,构成下图:
在这里插入图片描述

  • 应注意,在转化后,虽然 坐标发生改变,但是对应计算后的 距离并未改变

因此,该题将曼哈顿距离转化为切比雪夫距离后,对于每一个点,只需要计算 以其为中心,边长为 2 d 2d 的正方形区域内(不包括边缘)有多少个点 即可。



以下代码:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long LL;
const LL INF=0x3f3f3f3f3f3f3f3f;
const int MOD=1e9+7;
const int maxn=1e5+10;
int N,d,L;
vector<int> v[2*maxn];
int c[maxn*2];
int lowbit(int x)
{
    return x&(-x);
}
void updata(int i,int k)   //令a[i]+k
{
    while(i<=4*L)
    {
        c[i]+=k;
        i+=lowbit(i);
    }
}
int query(int i)     //sum[l~r]=query(r)-query(l-1)
{
    int ret = 0;
    while(i>0)
    {
        ret+=c[i];
        i-=lowbit(i);
    }
    return ret;
}
int main()
{
    scanf("%d %d %d",&N,&d,&L);
    for(int i=1;i<=N;i++)
    {
        int x,y,xx,yy;
        scanf("%d %d",&x,&y);
        xx=x+y+2*L;     //转化,并加上2*L将其转为正数
        yy=x-y+2*L;
        v[xx].push_back(yy);   //v[x]中存放横坐标为x的点的纵坐标y
    }
    LL ans=0;
    for(int x=0;x<=4*L;x++)    //对每个点,仅查找其左方(正方形左半边)有多少范围内的点
    {
        for(auto y:v[x])
        {
            ans+=query(min(4*L,y+d-1))-query(max(0,y-d));  //查找范围内的点数
            updata(y,1);                                   //更新范围内的点
        }
        if(x-d+1>=0)
        {
            for(auto y:v[x-d+1])    //删除超出范围的点
                updata(y,-1);
        }
    }
    printf("%lld\n",1LL*N*(N-1)/2-ans);  //N*(N-1)/2为总的点对数量
    return 0;
}

发布了214 篇原创文章 · 获赞 40 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Ratina/article/details/103213619