AtCoder [ABC351E] Jump Distance Sum 题解 [ 绿 ] [ 数学 ]

原题


场上差点就想出来了,就差一个旋转坐标轴了。

初步分析

首先来看如何判断两个点能不能走到,这可以看成下面的一张网格图,相同颜色的格子相互连通。

因此根据瞪眼法,可以把这些格子分为 $ (x_i + y_i) \mod 2 =1$ 和 $ (x_i + y_i) \mod 2 =0$ 的两部分。

然后观察位置 \((x,y)\) 可以跳到 \((x+1,y+1) , (x+1,y-1) , (x-1,y+1) , (x-1,y-1)\) ,很容易发现只能斜向跳跃

所以就可以把整个坐标轴旋转一个 \(45°\) 来观察。

但这样还是不好看,根据等腰直角三角形的三边关系,我们可以再给坐标系的单位长度乘上 \(\sqrt 2\)

于是就得到了下图,有空白是因为乘了之后会出现空隙。

再简单用全等一线三等角模型证明一下,就可以导出坐标 \((x,y)\) 会变成 \((x+y,y-x)\)

注意:由于进行了扩倍的操作,所以需要将最后求得的答案 \(/2\)

具体实现

不难发现,任意两点间的跳跃步数可以转化为他们之间的曼哈顿距离

而曼哈顿距离有一个特点:可以将 \(x,y\) 拆开来进行计算。

于是,我们可以把一组点的 \(x\)\(y\) 分别拆开然后再来求和。这个操作要在两组之间分别进行。

公式为 :

\[\sum_{i=1}^{N-1}{\sum_{j=i+1}^{N}{\text{dist}(P_i,P_j)}}=\sum_{i=1}^{N-1}{\sum_{j=i+1}^{N}{|x_i-x_j|}} + \sum_{i=1}^{N-1}{\sum_{j=i+1}^{N}{|y_i-y_j|}} \]

那么在 \(O(n)\) 的时间里计算出这些就简单了。

先给 \(x\)\(y\) 的数组简单排个序,以保证求得的答案为整数。

然后用一个 \(tmp\) 变量记录 \(\sum_{i=1}^{j-1}{(x_j-x_i)}\) ,每次统计到下一个 \(j\) 就把 \(tmp\) 加上 \(j*(x_j-x_{j-1})\) 。这个做法把它抽象成线段也许会更好理解。

对于 \(y\) 数组也同理,把结果加起来就行了。

还是挺需要思维的。

代码

#include <bits/stdc++.h>
using namespace std;
struct dot{
	long long x,y;
}d;
vector<dot>vd1,vd2;
vector<long long>v11,v12,v21,v22;
int n;
long long ans=0;
int main()
{
	cin>>n;
	//点分组
	for(int i=1;i<=n;i++)
	{
		cin>>d.x>>d.y;
		if((d.x+d.y)%2==0)vd1.push_back(d);
		else vd2.push_back(d);
	}
	//拆散并转换点坐标
	for(int i=0;i<vd1.size();i++)
	{
		v11.push_back(vd1[i].x+vd1[i].y);
		v12.push_back(vd1[i].y-vd1[i].x);
	}
	for(int i=0;i<vd2.size();i++)
	{
		v21.push_back(vd2[i].x+vd2[i].y);
		v22.push_back(vd2[i].y-vd2[i].x);
	}
	//排序
	sort(v11.begin(),v11.end());
	sort(v12.begin(),v12.end());
	sort(v21.begin(),v21.end());
	sort(v22.begin(),v22.end());
	//统计结果
	long long tmp=0;
	for(int i=1;i<v11.size();i++)
	{
		tmp+=i*(v11[i]-v11[i-1]);
		ans+=tmp;
	}
	tmp=0;
	for(int i=1;i<v12.size();i++)
	{
		tmp+=i*(v12[i]-v12[i-1]);
		ans+=tmp;
	}
	tmp=0;
	for(int i=1;i<v21.size();i++)
	{
		tmp+=i*(v21[i]-v21[i-1]);
		ans+=tmp;
	}
	tmp=0;
	for(int i=1;i<v22.size();i++)
	{
		tmp+=i*(v22[i]-v22[i-1]);
		ans+=tmp;
	}
	cout<<ans/2;
	return 0;
}
posted @ 2024-04-28 23:58  KS_Fszha  阅读(6)  评论(0编辑  收藏  举报