Points Created by LXC on Wed Jun 14 13:11:47 2023
https://codeforces.com/problemset/problem/76/E
ranting: 1700
tag: implementation, math
problem 给出二维平面上的n个整数坐标点。
求所有两个坐标的直线距离的平方之和。
solution 暴力做法是枚举任意两个点求其距离的平方,然后累加到答案中。时间复杂度会超时。
现在考虑优化到.
对于两个点和的距离的平方计算公式为,也就是说我们可以分别计算x和y的贡献。
举个例子来说,如果给出的坐标为
答案应当是
可以拆分为和
可以给x以及y坐标排序再寻找相邻前缀是否存在子问题的关系。
设给出的n个坐标的x值排序后为;设给出的n个坐标的y值排序后为。
定义状态为中任意两个点之间的距离平方和。
为方便计算和的递推关系,设dx是排序后相邻两个坐标的距离,。
我们观察一个例子
通过观察得到递推式,其中。。
对于n个点的y值同理可以定义状态为中任意两个点之间的距离平方和。。得到递推式,其中。
至此为所求。
code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include <bits/stdc++.h> #define SINGLE_INPUT #define ll long long #define ull unsigned long long #define N 100005 #define MOD 998244353 using namespace std;ll x[N], y[N]; ll dx[N], dy[N]; ll r[N], c[N]; ll R[N], C[N]; void sol () { int n; cin >> n; for (int i = 1 ; i <= n; i++) { cin >> x[i] >> y[i]; } sort (x + 1 , x + n + 1 ); sort (y + 1 , y + n + 1 ); for (int i = 1 ; i < n; i++) { dx[i] = x[i + 1 ] - x[i]; dy[i] = y[i + 1 ] - y[i]; } for (int i = 1 ; i < n; i++) { r[i] += r[i - 1 ] + i * dx[i]; c[i] += c[i - 1 ] + i * dy[i]; } R[1 ] = dx[1 ] * dx[1 ]; C[1 ] = dy[1 ] * dy[1 ]; for (int i = 2 ; i < n; i++) { R[i] = 2 * R[i - 1 ] - R[i - 2 ] + i * dx[i] * dx[i] + 2 * r[i - 1 ] * dx[i]; C[i] = 2 * C[i - 1 ] - C[i - 2 ] + i * dy[i] * dy[i] + 2 * c[i - 1 ] * dy[i]; } cout << R[n - 1 ] + C[n - 1 ] << "\n" ; } int main () { cout << setprecision (15 ) << fixed; ios::sync_with_stdio (false ); cin.tie (0 ); cout.tie (0 ); #ifndef SINGLE_INPUT int t; cin >> t; while (t--) { sol (); } #else sol (); #endif return 0 ; }