题意
给你 n n n个点,其整数坐标为 x 1 , … x n x_1,\dots x_n x1,…xn,它们位于一条数线上。
对于某个整数 s s s,我们构造线段 [ s , x 1 s,x_1 s,x1], [ s , x 2 s,x_2 s,x2], … \dots …, [ s , x n s,x_n s,xn]。请注意,如果是 [ x i , s x_i,s xi,s],那么线段看起来就像[ x i , s x_i,s xi,s]。线段 [ a , b a, b a,b]覆盖了所有整数点 a , a + 1 , a + 2 , … , b a, a+1, a+2, \dots, b a,a+1,a+2,…,b。
我们将点 p p p的幂定义为与坐标为 p p p的点相交的线段数,记为 f p f_p fp。
您的任务是计算每个 s ∈ { x 1 , … , x n } s \in \{x_1,\dots,x_n\} s∈{x1,…,xn}的 ∑ p = 1 1 0 9 f p \sum\limits_{p=1}^{10^9}f_p p=1∑109fp,即从 1 1 1到 1 0 9 10^9 109的所有整数点的 f p f_p fp之和。
例如,如果初始坐标为 [ 1 , 2 , 5 , 7 , 1 ] [1,2,5,7,1] [1,2,5,7,1],我们选择 s = 5 s=5 s=5,那么线段将是 [ 1 , 5 ] [1,5] [1,5], [ 2 , 5 ] [2,5] [2,5], [ 5 , 5 ] [5,5] [5,5], [ 5 , 7 ] [5,7] [5,7], [ 1 , 5 ] [1,5] [1,5].这些点的幂将是 f 1 = 2 , f 2 = 3 , f 3 = 3 , f 4 = 3 , f 5 = 5 , f 6 = 1 , f 7 = 1 , f 8 = 0 , … , f 1 0 9 = 0 f_1=2, f_2=3, f_3=3, f_4=3, f_5=5, f_6=1, f_7=1, f_8=0, \dots, f_{10^9}=0 f1=2,f2=3,f3=3,f4=3,f5=5,f6=1,f7=1,f8=0,…,f109=0.它们的和为 2 + 3 + 3 + 3 + 5 + 1 + 1 = 18 2+3+3+3+5+1+1=18 2+3+3+3+5+1+1=18。
输入
第一行包含一个整数 t t t ( 1 ≤ t ≤ 1 0 4 1\le t\le 10^4 1≤t≤104)–测试用例数。
每个测试用例的第一行包含一个整数 n n n ( 1 ≤ n ≤ 2 ⋅ 1 0 5 1 \le n \le 2\cdot 10^5 1≤n≤2⋅105)–点数。
第二行包含 n n n个整数 x 1 , x 2 … x n x_1,x_2 \dots x_n x1,x2…xn ( 1 ≤ x i ≤ 1 0 9 1 \le x_i \le 10^9 1≤xi≤109)–点的坐标。
保证所有测试用例的 n n n值之和不超过 2 ⋅ 1 0 5 2\cdot 10^5 2⋅105。
输出
对于每个测试案例,输出 n n n个整数,其中第 i i i个整数等于第 s = x i s=x_i s=xi个整数的所有点的幂之和。
思路
说了这么多废话,其实求得就是数组每个元素和其他元素差的绝对值之和 + n +n +n
举个例子 对于数组 [ 1 , 2 , 5 , 7 , 1 1, 2, 5, 7, 1 1,2,5,7,1] , , , 输出为 [ 16 , 15 , 18 , 24 , 16 16, 15, 18, 24, 16 16,15,18,24,16]
16
=
∣
1
−
1
∣
+
∣
1
−
2
∣
+
∣
1
−
5
∣
+
∣
1
−
7
∣
+
∣
1
−
1
∣
+
5
16=|1-1|+|1-2|+|1-5|+|1-7|+|1-1|+5
16=∣1−1∣+∣1−2∣+∣1−5∣+∣1−7∣+∣1−1∣+5
15
=
∣
2
−
1
∣
+
∣
2
−
2
∣
+
∣
2
−
5
∣
+
∣
2
−
7
∣
+
∣
2
−
1
∣
+
5
15=|2-1|+|2-2|+|2-5|+|2-7|+|2-1|+5
15=∣2−1∣+∣2−2∣+∣2−5∣+∣2−7∣+∣2−1∣+5
18
=
∣
5
−
1
∣
+
∣
5
−
2
∣
+
∣
5
−
5
∣
+
∣
5
−
7
∣
+
∣
5
−
1
∣
+
5
18=|5-1|+|5-2|+|5-5|+|5-7|+|5-1|+5
18=∣5−1∣+∣5−2∣+∣5−5∣+∣5−7∣+∣5−1∣+5
24
=
∣
7
−
1
∣
+
∣
7
−
2
∣
+
∣
7
−
5
∣
+
∣
7
−
7
∣
+
∣
7
−
1
∣
+
5
24=|7-1|+|7-2|+|7-5|+|7-7|+|7-1|+5
24=∣7−1∣+∣7−2∣+∣7−5∣+∣7−7∣+∣7−1∣+5
接下来那么问题就变得很简单了,先排序后求前缀和即可。
举个例子
原数组
a
:
1
,
2
,
5
,
7
,
1
a :1, 2, 5, 7, 1
a:1,2,5,7,1
数组
b
:
1
,
1
,
2
,
5
,
7
b:1, 1, 2, 5, 7
b:1,1,2,5,7
数组
s
u
m
:
1
,
2
,
4
,
9
,
16
sum:1, 2, 4, 9, 16
sum:1,2,4,9,16
对 b b b数组进行二分就可以得到它的位置 p o s pos pos,剩下的用前缀和知识就可以求出答案了。
完整代码
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
#define int long long
const int N = 1e6 + 10 , mod = 998244353, M = 2 * N;
typedef pair<int, int> PII;
typedef long long ll;
const int INF_MAX = 0x3f3f3f3f3f3f3f3f;
int a[N], b[N], sum[N];
void solve()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i], b[i] = a[i];
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i++)sum[i] = sum[i - 1] + a[i];
vector<int>ans;
for (int i = 1; i <= n; i++)
{
int pos = lower_bound(a + 1, a + 1 + n, b[i]) - a;
//cout << pos << endl;
int num1 = pos - 1;
int num2 = n - pos;
int t1 = abs(b[i] * num1 - sum[pos - 1]);
int t2 = abs(sum[n] - sum[pos] - num2 * b[i]);
//cout << t1 << " " << t2 << endl;
ans.push_back(t1 + t2 + n);
}
for (auto i : ans)
cout << i << " ";
cout << '\n';
}
signed main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T = 1;
cin >> T;
while (T--)solve();
return 0;
}