POJ3244-数学公式

1 篇文章 0 订阅

题目

POJ3244

题意

公式求值。

思路

from discuss
定义两个三元组I(xi,yi,zi)和J(xj,yj,zj),(可以看做是空间中的点)
他们的距离为D(I,J)=max{xi-xj,yi-yj,zi-zj}-min{xi-xj,yi-yj,zi-zj},
给定n个三元组(n<=200000),求任意两个三元组的差的和
抽化出来的模型是 max(a,b,c)-min(a,b,c),这个东西吧他放在数轴上 a,b,c
我们要求最大和最小的差就是这三个点构成的线段的距离,那么我们这里再变通下 是不是端点到中间那个点的距离
其实画出这个图的时候,就可以看到这个距离为(|a-b|+|b-c|+|c-a|)/2,这样我们并不需要关心中间的那个
对应到题目中的原型,就是(|(xi-xj)-(yi-yj)|+|(yi-yj)-(zi-zj)|+|(zi-zj)-(xi-xj)|)/2;
对应到同一个点上就是(|(xi-yi)-(xj-yj)|+|(yi-zi)-(yj-zj)|+|(zi-xi)-(zj-xj)|)/2;
设a=(xi-yi),b=(yi-zi),c=(zi-xi),原问题等价为(|ai-aj|+|bi-bj|+|ci-cj|)/2;
然后三个可以完全分开完全独立的计算,并不影响其他两元,这里要加个优化,就是按从小到大排序出来
我们只需要算出每个位置上,他贡献了多少次加法,贡献了多少次减法即可
举个例子,目前把a的部分排序了,对于第i个,他前面的比它小,所以在和i点比较时i点贡献了i次加,对后面的n-i个点
向他们贡献了n-i次减法

代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const int mx = 200005;
ll x[mx],y[mx],z[mx];
int main(){
//    freopen("t.in","r",stdin);
//    freopen("t.out","w",stdout);
    int n,a,b,c;
    long long ans=0;
    while(scanf("%d",&n)&&n){
        ans=0;
        for(int i=0;i<n;i++){
            scanf("%d%d%d",&a,&b,&c);
            x[i]=a-b;
            y[i]=b-c;
            z[i]=c-a;
        }
        sort(x,x+n);
        sort(y,y+n);
        sort(z,z+n);
        for(int i=0;i<n;i++){
            ans+=(2*i-n+1)*(x[i]+y[i]+z[i]);
        }
        printf("%I64d\n",ans/2);
    }
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值