AtCoder Beginner Contest 351 E题 Jump Distance Sum

E题:Jump Distance Sum

标签:思维
题意:在坐标平面上,有 N N N个点 P 1 , P 2 , … , P N P_1,P_2,…,P_N P1,P2,,PN,其中点 P i P_i Pi的坐标为 ( X i , Y i ) (X_i,Y_i) (Xi,Yi)
两点 A A A B B B之间的距离 d i s t ( A , B ) dist(A,B) dist(A,B)定义如下:
一只兔子最初位于点 A A A。位置为 ( x , y ) (x,y) (x,y)的兔子可以跳跃到
( x + 1 , y + 1 ) 、 ( x + 1 , y − 1 ) 、 ( x − 1 , y + 1 ) (x+1,y+1) 、 (x+1,y−1) 、 (x−1,y+1) (x+1,y+1)(x+1,y1)(x1,y+1) ( x − 1 , y − 1 ) (x−1,y−1) (x1,y1)
d i s t ( A , B ) dist(A,B) dist(A,B)被定义为从 A A A点到 B B B点所需的最少跳跃次数。
如果经过任意次数的跳跃都无法从点 A A A到达点 B B B,则设为 d i s t ( A , B ) = 0 dist(A,B)=0 dist(A,B)=0
计算总和 ∑ i = 1 N − 1 ∑ j = i + 1 N dist ( P i , P j ) \displaystyle\sum_{i=1}^{N-1}\displaystyle\sum_{j=i+1}^N \text{dist}(P_i,P_j) i=1N1j=i+1Ndist(Pi,Pj)
题解:兔子的移动是对角移动,不太方便进行操作。我们可以把坐标轴旋转 45 % 45\% 45%,并缩放 2 \sqrt2 2 倍。那么 ( x , y ) (x,y) (x,y)点移动到 ( x + y , x − y ) (x+y,x-y) (x+y,xy)。比如 ( 2 , 2 ) (2,2) (2,2)变成 ( 2 2 , 0 ) (2\sqrt2,0) (22 ,0),放大 2 \sqrt2 2 倍,为 ( 4 , 0 ) (4,0) (4,0)
原来位置为 ( x , y ) (x,y) (x,y)的兔子可以跳跃到
( x + 1 , y + 1 ) 、 ( x + 1 , y − 1 ) 、 ( x − 1 , y + 1 ) (x+1,y+1) 、 (x+1,y−1) 、 (x−1,y+1) (x+1,y+1)(x+1,y1)(x1,y+1) ( x − 1 , y − 1 ) (x−1,y−1) (x1,y1)
我们转换后兔子可以从 ( x + y , x − y ) (x+y,x-y) (x+y,xy)跳跃到 ( x + y + 2 , x − y ) 、 ( x + y , x − y + 2 ) 、 ( x + y , x − y − 2 ) (x+y+2,x−y)、 (x+y,x−y+2) 、 (x+y,x−y−2) (x+y+2,xy)(x+y,xy+2)(x+y,xy2) ( x + y − 2 , x − y ) (x+y−2,x−y) (x+y2,xy)
转换成更通用的式子:兔子可以从 ( x , y ) (x,y) (x,y)跳跃到 ( x + 2 , y ) 、 ( x , y + 2 ) 、 ( x , y − 2 ) (x+2,y)、 (x,y+2) 、 (x,y−2) (x+2,y)(x,y+2)(x,y2) ( x − 2 , y ) (x−2,y) (x2,y)
那么我们观察到每次跳跃的距离都是偶数,也就是说如果 A = ( x 1 , y 1 ) , B = ( x 2 , y 2 ) A=(x_1,y_1),B=(x_2,y_2) A=(x1,y1)B=(x2,y2) ∣ x 1 − x 2 ∣ |x_1-x_2| x1x2不能被 2 2 2整除,或者 ∣ y 1 − y 2 ∣ |y_1-y_2| y1y2不能被 2 2 2整除,那么兔子就无法从 A A A到达 B B B
对于能到达的情况跳跃的最少次数显然等于 1 2 ( ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ ) \frac{1}{2}(\lvert x_1-x_2\rvert+\lvert y_1-y_2\rvert) 21(∣x1x2+y1y2∣)
也就是说对于能够相互到达的两个点 A A A B B B,他们的转化后的 x x x坐标的奇偶性和 y y y坐标的奇偶性必须相同。
我们可以统计一下对应转化后的 x x x奇/偶, y y y奇/偶的情况。然后去求一下对应情况下的跳跃次数。
这边举个例子:假设 x x x奇, y y y奇的情况,得到的 x x x的序列为
1     3     8     13 1\ \ \ 3\ \ \ 8\ \ \ 13 1   3   8   13
第二个 3 到 1 的距离为 1 段 2 的距离。
第三个 8 到前面两个点的距离为 2 段 8 的距离减去前缀前两个距离之和,即 2 ∗ 8 − ( 1 + 3 ) 2*8-(1+3) 28(1+3)
第四个 13 到前面两个点的距离为 3 段 13 的距离减去前缀 3 个距离之和,即 3 ∗ 13 − ( 1 + 3 + 8 ) 3*13-(1+3+8) 313(1+3+8)
注意题目中,转化后是 2 2 2的距离跳的,所以跳跃的次数最后要除以 2 2 2
代码

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
ll n, X, Y, ans = 0;
vector<ll> x[2][2], y[2][2];

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> X >> Y;
        x[(X+Y)%2][abs(X-Y)%2].push_back(X+Y);
        y[(X+Y)%2][abs(X-Y)%2].push_back(X-Y);
    }

    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            int nx = x[i][j].size();
            int ny = y[i][j].size();
            if (nx == 0) continue;

            sort(x[i][j].begin(), x[i][j].end());
            sort(y[i][j].begin(), y[i][j].end());

            ll prex = x[i][j][0], prey = y[i][j][0];;
            for (int k = 1; k < nx; k++) {
                ans += k * x[i][j][k] - prex;
                prex += x[i][j][k];
            }
            for (int k = 1; k < ny; k++) {
                ans += k * y[i][j][k] - prey;
                prey += y[i][j][k];
            }
        }
    }

    cout << ans / 2;
    return 0;
}
  • 42
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值