poj 3244 找规律
题意:定义两个三元组(xi, yi, zi)和(xj, yj, zj),他们的距离为dist = max( xi-xj, yi-yj, zi-zj) - min(xi-xj, yi-yj, zi-zj),给定n个三元组(n<=200000),求任意两个三元组的距离之和。
令a=xi-xj,b=yi-yj,c=zi-zj,问题转化为dist = max(a, b, c) - min(a, b, c),考虑数轴上的三个点a b c, dist为它们覆盖的线段长度。dist = ( |a-b| + |b-c| + |c-a| ) / 2。这样一来就不用考虑a b c 谁大谁小。。
所以dist = ( | (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。
令ai=xi-yi, bi=yi-zi, ci=zi-xi, dist = ( |ai-aj| + |bi-bj| + |ci-cj| ) / 2,其中a b c可以分开求。
例如求a,先从小到大排序,考虑排序后的a[i],前面有 i 个比a[i]小的数,a[i]要减去它们,于是a[i]贡献了 i 次正数;后面有n-1-i个比a[i]大的数,每个数都要减a[i],a[i]贡献了n-1-i 次负数。
const int M = 200005; int n, x, y, z; int a[M], b[M], c[M]; LL ans; int main(){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); #endif while( scanf("%d", &n), n ){ FOR(i, 0, n){ scanf("%d%d%d", &x, &y, &z); a[i] = x-y; b[i] = y-z; c[i] = z-x; } sort(a, a+n); sort(b, b+n); sort(c, c+n); ans = 0; FOR(i, 0, n) ans += (LL)((i<<1)-1-n) * ( a[i] + b[i] + c[i] ); printf("%I64d\n", ans>>1); } return 0; }