[ABC351E] Jump Distance Sum
一道 tang problem,浪费我大半个下午,使我十分痛苦,呜呜呜呜。
题意概括
我们有 \(N\) 个点,要求 \(\sum_{i=1}^{N-1}\sum_{j=i+1}^{N}dis(P_i,P_j)\)
\(P_i\) 指的是第 \(i\) 个点。
我们定义 \(dis(P_i,P_j)\) 为从 \(P_i\) 到 \(P_j\) 的最小操作次数。
关于操作,我们假设现在处于 \((x,y)\),我们可以到达 \((x+1,y+1)\),\((x+1,y-1)\),\((x-1,y+1)\),\((x-1,y-1)\)。
就是这个亚子。
杂技吧做?
怎么办!!!怎么办!!!怎么办!!!
劳资根本不会呜呜呜呜。
我们先考虑一下一个 \(dis\) 怎么求,不然暴力都不行。
我去理性思考了一波,有的点直接确实没法到达,我们从图上难以分析。
这个问题就是 \((x_i-x_j,y_i-y_j)\),我们可以选择去每一次将这么两个数任何一个加一或者减一。
我们惊人的发现了一个秘密的事情,辣就是这个东西如果加起来是偶数才行,主要是这个东西总体上不变或者加二减二。
所以我们按照 \(x+y\) 的奇偶性分成两类。
这样我们就能在每一类上求出来可能的贡献了。
对于两个,这个贡献是 \(max(|x_1-x_2|,|y_1-y_2|)\)。
所以我们起码会暴力了,但是我不到这个怎么搞正解......
所以我们去看一看这个东西是什么玩意。
所有的问题其实就在这 \(max\) 上了,有这个东西就让我很绝望,所以我发现了世界的真相。
这个东西不就是切比雪夫距离嘛!!!
大家都知道,切比雪夫距离和曼哈顿距离是阔以相互转化的。
放一下怎么转化,防止之后我忘掉......
\((x,y)\to(x+y,x-y)\),原坐标中曼哈顿距离等于新坐标中切比雪夫距离。
\((x,y)\to(\frac{x+y}{2},\frac{x-y}{2})\),原坐标中切比雪夫距离等于新坐标中曼哈顿距离。
我们就直接转换,这个/2到最后处理,因为我们不方便搞小数。
就这么转化一波,问题就是求到所有点的曼哈顿距离就行了。
wow,没辣。
点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MN=1e6+116;
int n, ans=0;
vector <int> vec[4];
signed main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); cin>>n;
for(int i=1,x,y; i<=n; ++i){
cin>>x>>y;
if((x+y)%2==0){
vec[0].push_back(x+y);
vec[1].push_back(x-y);
}else{
vec[2].push_back(x+y);
vec[3].push_back(x-y);
}
}
for(int i=0; i<4; ++i){
sort(vec[i].begin(),vec[i].end());
int siz=vec[i].size();
for(int j=0; j<siz; ++j){
ans+=vec[i][j]*(2*j+1-siz);
}
}
cout<<ans/2<<'\n';
return 0;
}

浙公网安备 33010602011771号