poj 3244 公式推导 叉姐的魔法训练

Difference between Triplets
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 2723 Accepted: 919

Description

For every pair of triplets, Ta = (Ia, Ja, Ka) and Tb = (Ib,Jb, Kb), we define the difference value betweenTa and Tb as 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?

Input

The input consists of several test cases.
Each test case begins with a line containing an integer N, denotes the number of triplets. Assume that we number the triplets as T1, T2, ... , TN. Then, there are following N lines, each line contains three integers, giving the elements of each triplet.
A case with N = 0 indicates the end of the input.

Output

For each case, output a line with the sum of difference values between every unordered pair of triplets.

Sample Input

2
1 2 3
3 2 1
3
1 3 2
4 0 7
2 2 9
0

Sample Output

4
20

Hint

Case 1: D( T1, T2)=4
Case 2: D( T1, T2)+ D( T1, T3)+ D( T2, T3)=8+8+4=20

You can assume that N, the number of triplets in each case, will not exceed 200,000 and the elements in triplets fit into [-10 6,10 6].
The size of the input will not exceed 5 MB.



题意:

两个三元组(x1,y1,z1)(x2,y2,z2)的距离如下定义

D = max {x1 − x2, y1 − y2, z1 − z2} − min {x1 − x2, y1 − y2, z1 − z2}

现在给你n个三元组,让你求出任意两个三元组的距离之和。


题解:

a = x1-x2, b=y1-y2, c=z1-z2

D = max {a,b,c} − min {a,b,c}

这样的话 D = (|a-b|+|b-c|+|c-a|)/2。在数轴上画一下即可看清楚

D = (|(x1-x2)-(y1-y2)|+|(y1-y2)-(z1-z2)|+|(z1-z2)-(x1-x2)|)/2

   = (|(x1-y1)-(x2-y2)|+|(y1-z1)-(y2-z2)|+|(z1-x1)-(z2-x2)|)/2

再令 a1=x1-y1, b1=y1-z1, c1=z1-x1

得  D = (|a1-a2|+|b1-b2|+|c1-c2|)/2


发现规律:

每个三元组需要与其它n-1个三元组计算一次

那么每个a,b,c都要与其他三元组的a,b,c计算一次

为了将绝对值去掉,对所有的a   b   c 分别排序

在草稿纸上面列举四个或者更多三元组的情况,然后就可以得到公式

(n - 2*i - 1)*a[ i ] + (n - 2*i - 1)*b[ i ] + (n - 2*i - 1)*c[ i ]



注意:需要用__int64   不能用long long

尤其是最后一个循环的变量也是这样的

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define MAXN 200010
int a[MAXN],b[MAXN],c[MAXN];

int cmp(const void *x,const void *y)
{
    return *(int *)y - *(int *)x;
}

int main()
{
    int n;
    int x,y,z;
    //freopen("in.txt","r",stdin);
    while(scanf("%d",&n)&&n)
    {
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&x,&y,&z);
            a[i]=x-y,b[i]=y-z,c[i]=z-x;
        }
        qsort(a+1,n,sizeof(a[0]),cmp);
        qsort(b+1,n,sizeof(b[0]),cmp);
        qsort(c+1,n,sizeof(c[0]),cmp);

        __int64 ans=0;
        for(__int64 i=1;i<=n;i++){
            ans+=(n-2*i-1)*a[i];
            ans+=(n-2*i-1)*b[i];
            ans+=(n-2*i-1)*c[i];
        }
        printf("%I64d\n",ans/2);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值