3244 Difference between Triplets 好题啊 有点类似求SIGMA(线段和)的题目
2010-10-02 10:02
218 查看
Difference between Triplets
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.
Output
For each case, output a line with the sum of difference values between every unordered pair of triplets.
Sample Input
Sample Output
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 [-106,106].
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)。
*/
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 1825 | Accepted: 460 |
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.
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 [-106,106].
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)。
*/
相关文章推荐
- HDU 2509 Be the Winner(尼姆模板与hdu 1907类似的题目)
- 一道百度编程比赛的题目及类似的题目
- 类的继承关系,多态的体现,我的觉得题目还是有点欠缺
- 3Sum 等类似题目分析
- [置顶] Combination Sum系列的三个题目39,40,216--重要(和78. Subsets ,90. Subsets II类似)
- SyncML协议简述(和HTTP协议有点类似)
- POJ 3347 Kadj Squares 复杂的线段相交问题。这个题目是计算几何的扩大数据运算的典型应用 有时候扩大数据范围避免浮点误差,这个题就是应用
- 题目1198:a+b(高精度计算,好像有点问题)
- 完美的代价----蓝桥杯(一道有点启发的题目!)
- 第一次月赛题目—兔子与樱花(单源最短路。最后一分钟ac的,想想都有点小激动啊)
- HDOJ 题目4313 Matrix(类似克鲁斯卡尔)
- POJ1159 回文数(DP基础题目)+POJ3991(类似题目)
- 2013年3月30日竞赛题目二 Sigma
- Android Studio 是谷歌基于IntelliJ IDEA开发的安卓开发工具,有点类似 Eclipse ADT,Android Studio 提供了集成的 Android 开发工具用于开发和调
- 一道类似SQL题目,接近实际,
- poj 2996详解(题目很简单只是要认真看清楚题目,我写的代码有点长了,嘻嘻)
- Divide Two Integers题解以及类似题目的总结
- 美团内推 类似题目
- 【洛谷 2016】战略游戏 树形dp经典题目(类似没有上司的舞会)
- [HDU] 1072 Nightmare 和HDU1180有点类似