AtCoder Beginner Contest 351 E Solution

AT_abc351_e Jump Distance Sum

题目简述

一个平面直角坐标系上有 \(n\) 个点,定义两个点 \(a\)\(b\) 之间的距离 \(\text{dist}(a,b)\) 如下。

定义一次合法移动,为将一个点 \((x,y)\) 移动至 \((x+1,y+1)\)\((x+1,y-1)\)\((x-1,y+1)\)\((x-1,y-1)\)

\(a\) 可以通过有限次合法移动移动至点 \(b\) ,则 \(\text{dist}(a,b)\)\(a\) 通过合法移动移动至 \(b\) 的最小次数。

\(a\) 无法通过有限次合法移动移动至点 \(b\) ,则 \(\text{dist}(a,b)=0\)

\[\sum_{i=1}^{n-1}\sum_{j=i+1}^n \text{dist}(p_i,p_j) \]

省流

对顶点坐标进行重映射后分组通过前缀和分别求 \(x\) 坐标与 \(y\) 坐标的距离。

AtCoder 的思维性又回来了。

思路

由于点是斜向走的,直接求显然难度较大。

考虑对点的坐标重映射。

定义 \(p=x+y,q=x-y\)

原坐标系上一点 \(A(x,y)\)重映射\(A'(p,q)\)

则,题面中提到的移动 \((x+1,y+1)\)\((x+1,y-1)\)\((x-1,y+1)\)\((x-1,y-1)\) ,将会分别被映射为 \((p+2,q)\)\((p,q+2)\)\((p,q-2)\)\((p-2,q)\)

经过重映射后可以看出,可以互相到达的两个点 \(A\)\(B\) ,他们的 \(p\)\(q\) 的奇偶性一定相同。

于是就可以使用一般平面直角坐标系上曼哈顿距离的求解方法对距离进行求解。

最终的结果要除以 \(2\)

时间复杂度 \(O(n\log n)\)

代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
using ll = long long;
const int N = 2e5 + 10;
vector<ll> x[2][2], y[2][2];
int n, tx, ty;
ll res, tmp;
int main()
{
    scanf("%d", &n);
    for (int i = 1, sm, dv; i <= n; i++)
    {
        scanf("%d%d", &tx, &ty);
        sm = tx + ty, dv = tx - ty;
        x[sm % 2][abs(dv) % 2].push_back(sm);
        y[sm % 2][abs(dv) % 2].push_back(dv);
    }
    for (int a = 0; a < 2; a++)
    {
        for (int b = 0; b < 2; b++)
        {
            sort(x[a][b].begin(), x[a][b].end());
            sort(y[a][b].begin(), y[a][b].end());
            tmp = 0;
            for (int t = 1; t < x[a][b].size(); t++)
            {
                tmp += x[a][b][t] - x[a][b][0];
            }
            for (int t = 1; t < x[a][b].size(); t++)
            {
                res += tmp / 2;
                tmp -= (x[a][b][t] - x[a][b][t - 1]) * (x[a][b].size() - t);
            }
            tmp = 0;
            for (int t = 1; t < y[a][b].size(); t++)
            {
                tmp += y[a][b][t] - y[a][b][0];
            }
            for (int t = 1; t < y[a][b].size(); t++)
            {
                res += tmp / 2;
                tmp -= (y[a][b][t] - y[a][b][t - 1]) * (y[a][b].size() - t);
            }
        }
    }
    printf("%lld\n", res);
}
posted @ 2024-04-28 13:39  丝羽绫华  阅读(133)  评论(0编辑  收藏  举报