Difference between Triplets
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 1825 | Accepted: 460 |
Description
For every pair of triplets, Ta = (Ia, Ja, Ka) and Tb = (Ib, Jb, Kb), we define the difference value between Ta and Tb as follows:
D(Ta, Tb) = max {Ia − Ib, Ja − Jb, Ka − Kb} − min {Ia − Ib, Ja − Jb, Ka − Kb}
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.
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.
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.
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX = 200001;
__int64 a[MAX],b[MAX],c[MAX];
int main()
{
int n;
while(scanf("%d",&n)==1&&n)
{
for(int i=0;i<n;i++)
{
int x,y,z;scanf("%d%d%d",&x,&y,&z);
a[i]=x-y;
b[i]=y-z;
c[i]=x-z;
}
sort(a,a+n);sort(b,b+n);sort(c,c+n);
__int64 cnt=0;
for(int i=0;i<n;i++)
{
cnt+=i*a[i]-(n-i-1)*a[i];
cnt+=i*b[i]-(n-i-1)*b[i];
cnt+=i*c[i]-(n-i-1)*c[i];
}
printf("%I64d/n",cnt/2);
}
return 0;
}
/*
数据范围非常大,枚举必然不可,需要数学方法。这个题目巧妙之处在于,模型经过了层层的包装,
要想一下子有想法还真不容易。既然不能枚举了,这个max和min操作就不好办了,应该设法去掉。
max{a, b, c} - min{a, b, c} = |a - b| + |b - c| + | c - a| / 2,这个公式应该不难想到,
但是这只是第一步,因为引进了绝对值,依然不好做。可以先算出分子,最后再除2。
接下来需要一个等价变换,以a - b为例,a - b = xi - xj - yi + yj = (xi - yi) - (xj - yj),
同理把b - c、c - a都写成这种形式。这一步变换看似作用不大,但是假设我们算出所有的xi - yi之后
(i = 0... n - 1),将其排序,会发现,对于第i个xi - yi,它前面的都比它小,后面的都比它大。
而实际上,由于求任意两个三元组的差,肯定xi - yi会和任意的xj - yj都作差的,加了绝对值后,
它对最后的结果就会贡献i个(xi - yi),n - i - 1个-(xi - yi)。同样的方法算出所有的(yi - zi)和
(zi - xi),结果就能够求出来了。算法复杂度O(n * logn)。
*/
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX = 200001;
__int64 a[MAX],b[MAX],c[MAX];
int main()
{
int n;
while(scanf("%d",&n)==1&&n)
{
for(int i=0;i<n;i++)
{
int x,y,z;scanf("%d%d%d",&x,&y,&z);
a[i]=x-y;
b[i]=y-z;
c[i]=x-z;
}
sort(a,a+n);sort(b,b+n);sort(c,c+n);
__int64 cnt=0;
for(int i=0;i<n;i++)
{
cnt+=i*a[i]-(n-i-1)*a[i];
cnt+=i*b[i]-(n-i-1)*b[i];
cnt+=i*c[i]-(n-i-1)*c[i];
}
printf("%I64d/n",cnt/2);
}
return 0;
}
/*
数据范围非常大,枚举必然不可,需要数学方法。这个题目巧妙之处在于,模型经过了层层的包装,
要想一下子有想法还真不容易。既然不能枚举了,这个max和min操作就不好办了,应该设法去掉。
max{a, b, c} - min{a, b, c} = |a - b| + |b - c| + | c - a| / 2,这个公式应该不难想到,
但是这只是第一步,因为引进了绝对值,依然不好做。可以先算出分子,最后再除2。
接下来需要一个等价变换,以a - b为例,a - b = xi - xj - yi + yj = (xi - yi) - (xj - yj),
同理把b - c、c - a都写成这种形式。这一步变换看似作用不大,但是假设我们算出所有的xi - yi之后
(i = 0... n - 1),将其排序,会发现,对于第i个xi - yi,它前面的都比它小,后面的都比它大。
而实际上,由于求任意两个三元组的差,肯定xi - yi会和任意的xj - yj都作差的,加了绝对值后,
它对最后的结果就会贡献i个(xi - yi),n - i - 1个-(xi - yi)。同样的方法算出所有的(yi - zi)和
(zi - xi),结果就能够求出来了。算法复杂度O(n * logn)。
*/