题意
对于每一个三元组:
T
a
=
(
I
a
,
J
a
,
K
a
)
,
T
b
=
(
I
b
,
J
b
,
K
b
)
T_a=(I_a,J_a,K_a),T_b=(I_b,J_b,K_b)
Ta=(Ia,Ja,Ka),Tb=(Ib,Jb,Kb)定义:
D
(
T
a
,
T
b
)
=
max
{
I
a
−
I
b
,
J
a
−
J
b
,
K
a
−
K
b
}
−
min
{
I
a
−
I
b
,
J
a
−
J
b
,
K
a
−
K
b
}
D(T_a,T_b)=\max\{I_a-I_b,J_a-J_b,K_a-K_b\}-\min\{I_a-I_b,J_a-J_b,K_a-K_b \}
D(Ta,Tb)=max{Ia−Ib,Ja−Jb,Ka−Kb}−min{Ia−Ib,Ja−Jb,Ka−Kb}
求
∑
i
=
1
N
∑
j
=
i
+
1
N
D
(
T
i
,
T
j
)
\sum_{i=1}^{N}{\sum_{j=i+1}^{N}{D(T_i,T_j)}}
∑i=1N∑j=i+1ND(Ti,Tj) 的值。
数据范围:
N
≤
2
×
1
0
5
N\leq 2\times 10^5
N≤2×105,每个元素的范围:
[
−
1
0
6
,
1
0
6
]
[-10^6,10^6]
[−106,106]
分析
关键在于公式的化简:
max
(
a
,
b
,
c
)
−
min
(
a
,
b
,
c
)
=
∣
a
−
b
∣
+
∣
a
−
c
∣
+
∣
b
−
c
∣
2
\max(a,b,c)-\min(a,b,c)=\frac{|a-b|+|a-c|+|b-c|}{2}
max(a,b,c)−min(a,b,c)=2∣a−b∣+∣a−c∣+∣b−c∣
代入三元组,可得:
D
(
T
a
,
T
b
)
=
∣
(
I
a
−
J
a
)
−
(
I
b
−
J
b
)
∣
+
∣
(
J
a
−
K
a
)
−
(
J
b
−
K
b
)
∣
+
∣
(
I
a
−
K
a
)
−
(
I
b
−
K
b
)
∣
2
D(T_a,T_b)=\frac{|(I_a-J_a)-(I_b-J_b)|+|(J_a-K_a)-(J_b-K_b)|+|(I_a-K_a)-(I_b-K_b)|}{2}
D(Ta,Tb)=2∣(Ia−Ja)−(Ib−Jb)∣+∣(Ja−Ka)−(Jb−Kb)∣+∣(Ia−Ka)−(Ib−Kb)∣
现在,我们要想办法去掉绝对值。对每个
T
i
T_i
Ti,求出
(
I
i
−
J
i
)
,
(
I
i
−
K
i
)
,
(
J
i
−
K
i
)
(I_i-J_i),(I_i-K_i),(J_i-K_i)
(Ii−Ji),(Ii−Ki),(Ji−Ki),然后分别从小到大排序。对于
(
I
i
−
J
i
)
(I_i-J_i)
(Ii−Ji),假设它出现在排列后的第
x
x
x 个位置,那么他对最后的答案会有
x
−
1
x-1
x−1 个正的贡献,
n
−
x
n-x
n−x 个负的贡献,最终的贡献为
2
x
−
n
−
1
2x-n-1
2x−n−1。对其它两个同样处理,即可得到结果。
代码
#include <cstdio>
#include <algorithm>
#include <set>
#include <iostream>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int a[N],b[N],c[N];
int main(){
int n;
while(scanf("%d",&n),n!=0){
for(int i=1;i<=n;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
a[i]=x-y;
b[i]=x-z;
c[i]=y-z;
}
sort(a+1,a+1+n);
sort(b+1,b+1+n);
sort(c+1,c+1+n);
ll ans=0;
for(int i=1;i<=n;i++){
ans+=1LL*(2*i-n-1)*a[i];
ans+=1LL*(2*i-n-1)*b[i];
ans+=1LL*(2*i-n-1)*c[i];
}
printf("%lld\n",ans/2);
}
return 0;
}