公式

E - Jump Distance Sum 解説 by en_translator


Rotate the plane by \(45\) degrees with respect to the origin, and scale by \(\sqrt{2}\) times. Then, the point originally at \((X,Y)\) moves to \((X+Y,X-Y)\).
Let \((x_i,y_i)\) be the resulting coordinates of each point \(P_i\) after this transformation. Then, \(x_i=X_i+Y_i\) and \(y_i=X_i-Y_i\).

Next, we consider how the definition of \(\text{dist}(A,B)\) changes.
In the original definition, the rabbit can jump from \((X,Y)\) to \((X+1,Y+1)\), \((X+1,Y-1)\), \((X-1,Y+1)\), and \((X-1,Y-1)\);
thus, after the transformation, it can jump from \((X+Y,X-Y)\) to \((X+Y+2,X-Y)\), \((X+Y,X-Y+2)\), \((X+Y,X-Y-2)\), and \((X+Y-2,X-Y)\).
Replacing \(x=X+Y\) and \(y=X-Y\), it can jump from \((x,y)\) to \((x+2,y)\), \((x,y+2)\), \((x,y-2)\), and \((x-2,y)\).
The minimum number of jumps required to reach from \(A\) to \(B\) is the definition of \(\text{dist}(A,B)\) (or \(0\) if unreachable).

Hereinafter, we consider the problem after the transformation.
That is, we let \(P_i=(x_i,y_i)\), define \(\text{dist}(A,B)\), and consider the sum \(\displaystyle\sum_{i=1}^{N-1}\displaystyle\sum_{j=i+1}^N \text{dist}(P_i,P_j)\) with the aforementioned definition of \(\text{dist}(A,B)\).
Obviously, this yields the same answer as the original.

We further consider \(\text{dist}(A,B)\) for \(A=(x_1,y_1)\), \(B=(x_2,y_2)\). If \(x_1\not\equiv x_2 \pmod{2}\) or \(y_1\not\equiv y_2 \pmod{2}\), the rabbit cannot reach from \(A\) to \(B\), so \(\text{dist}(A,B)=0\). Otherwise, it evaluates to exactly half the Manhattan distance, \(\frac{1}{2}(\lvert x_1-x_2\rvert+\lvert y_1-y_2\rvert)\).

Noting that \(x_i=y_i+2Y_i\equiv y_i \pmod{2}\) for all \(i\), the \(N\) points can be classified into two groups: \(x_i\) and \(y_i\) are both even, or \(x_i\) and \(y_i\) are both odd. For two points \(A\) and \(B\) belonging to different groups, \(\text{dist}(A,B)=0\); for two different points belonging to the same group, \(\text{dist}(A,B)=\frac{1}{2}(\lvert x_1-x_2\rvert+\lvert y_1-y_2\rvert)\).

Let \(E=\{E_1,E_2,\ldots,E_{\lvert E\rvert} \}\) be the set of points whose \(x_i\) and \(y_i\) are both even, then \(\displaystyle\sum_{i=1}^{\lvert E\rvert-1}\displaystyle\sum_{j=i+1}^{\lvert E\rvert} \text{dist}(P_{E_i},P_{E_j}) =\frac{1}{2}\sum_{i=1}^{\lvert E\rvert-1}\displaystyle\sum_{j=i+1}^{\lvert E\rvert} \lvert x_{E_j}-x_{E_i} \rvert+\frac{1}{2}\sum_{i=1}^{\lvert E\rvert-1}\displaystyle\sum_{j=i+1}^{\lvert E\rvert} \lvert y_{E_j}-y_{E_i} \rvert\) .
\(\displaystyle\sum_{i=1}^{\lvert E\rvert-1}\sum_{j=i+1}^{\lvert E\rvert} \lvert x_{E_j}-x_{E_i} \rvert\) can be found as \(\displaystyle\sum_{i=1}^{\lvert E\rvert-1}\sum_{j=i+1}^{\lvert E\rvert} \lvert x_{E_j}-x_{E_i} \rvert=\sum_{i=1}^{\lvert E\rvert-1}\displaystyle\sum_{j=i+1}^{\lvert E\rvert} \lvert x'_j-x'_i \rvert= \sum_{i=1}^{\lvert E\rvert-1}\displaystyle\sum_{j=i+1}^{\lvert E\rvert} (x'_j-x'_i)= \sum_{i=1}^{\lvert E\rvert}(\lvert E\rvert+1-2i)x'_i\), where \((x'_1,x'_2,\ldots,x'_{\lvert E\rvert})\) is the sequence obtained by sorting \((x_{E_1},x_{E_2},\ldots,x_{E_{\lvert E\rvert}})\) in ascending order.

Applying the same discussion to \(y\) coordinates, one can find \(\displaystyle\sum_{i=1}^{\lvert E\rvert-1}\displaystyle\sum_{j=i+1}^{\lvert E\rvert} \text{dist}(P_{E_i},P_{E_j})\); adopting the same discussion to the group with odd \(x_i\) and \(y_i\), one can find the final sum.

Sorting \(x\) and \(y\) coordinates of the two groups costs \(O(N\log N)\) time, and the remaining computation costs can be done in \(O(N)\) time, so this problem can be solved in a total of \(O(N\log N)\) time, which is fast enough. Therefore, the problem has been solved.

Sample code in C++:

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

int main(void){
	int n,sz;
	long long x,y,ans=0;
	vector<long long>a[4];
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>x>>y;
		if((x+y)%2==0){
			a[0].push_back(x+y);
			a[1].push_back(x-y);
		}
		else{
			a[2].push_back(x+y);
			a[3].push_back(x-y);
		}
	}
	for(int i=0;i<4;i++){
		sort(a[i].begin(),a[i].end());
		sz=a[i].size();
		for(int j=0;j<sz;j++)ans+=a[i][j]*(2*j+1-sz);
	}
	cout<<(ans/2)<<endl;
	return 0;
}

投稿日時:
最終更新: