poj 3244 Difference between Triplets

3244 一个数学题

Difference between Triplets

For every pair of triplets, Ta = (Ia, Ja, Ka) and Tb= (Ib, Jb, Kb), we define the difference value between Ta and Tbas follows:

D(Ta, Tb) = max {IaIb, JaJb, KaKb} − min {IaIb, JaJb, KaKb}

Now you are given N triplets, could you write a program to calculate the sum of the difference values between every unordered pair of triplets?

 

给出N个三元组,将给出的三元组两两组合,分别求出D(Ta, Tb)的值。

若任意两个三元组为Ta = (Ia, Ja, Ka) and Tb= (Ib, Jb, Kb),

则:D(Ta, Tb) = max {IaIb, JaJb, KaKb} − min {IaIb, JaJb, KaKb}

最后求所有D(Ta, Tb)和的值

 

这道题有个很关键的公式,知道的就很容易做出来了

//公式max(a,b,c)-min(a,b,c)=(|a-b|+|b-c|+|a-c|)/2.

把a、b、c想成是数轴上的三个点就很容易得出上述公式了。

然而求出所有的|a-b|+|b-c|+|a-c|,再求和也不是简单的问题,所以进而继续化简得:

max {IaIb, JaJb, KaKb} − min {IaIb, JaJb, KaKb}

=(|(IaIb)—( JaJb)|+|(JaJb)—(KaKb)|+|( KaKb)-( IaIb)|)/2

= (|(IaJa)—(Ib—Jb)|+|(JaKa)—(JbKb)|+| (KaIa)—( KaIb)|)/2

如果令a=( IiJi),b=( JiKi),c=( KiIi),原问题等价为(|ai-aj|+|bi-bj|+|ci-cj|)/2,对于每个含a、b、c的绝对值式子可以分开求:
例如,根据ai,aj的大小即可知道在最后的求和式中贡献了多少次加法和减法。
将x数组排序,对于第xi个,他前面的比它小,所以在和i点比较时i点贡献了i次加,对后面的n-i个点向他们贡献了n-i次减法
 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<cmath>

 5 #include<algorithm>

 6 #define see(x) cout<<#x<<":"<<x<<endl;

 7 #define N 200010

 8 using namespace std;

 9 long long x[N], y[N], z[N];

10 

11 int main(){ 

12     int i, j, k, l, n, m;

13     long long a, b, c, sum;

14     while(~scanf("%d",&n)&&n){

15 

16         sum = 0;

17         for(i=0;i<n;i++){

18             scanf("%lld%lld%lld",&a,&b,&c);

19             x[i]=a-b;y[i]=b-c;z[i]=a-c;

20         }

21         sort(x,x+n); sort(y,y+n); sort(z,z+n);

22         for(i=0;i<n;i++){

23             sum += ((i-(n-1-i))*(x[i]+y[i]+z[i]));

24         }

25         cout<<sum/2<<endl;

26     }

27     return 0;

28 } 

 

 



                            

你可能感兴趣的:(diff)