题目链接: https://www.hackerrank.com/challenges/jim-and-the-challenge
题目大意: 给定d维空间的n个点,每个点有权值h[i],求sigma(i=1...n,j=i+1...n,h[i]*h[j]*dis(i,j))的值,其中dis(i,j)是两点的曼哈顿距离,d<=4,n<=100000.
题解: 根据曼哈顿距离的性质,每一维之间两两独立,所以可以分开来计算,
对于每一维,所要计算的值为sigma(i=1...n,j=i+1...n,(x[j]-x[i])*h[i]*h[j]),
先通过排序去绝对值,再考虑每一项对于答案的贡献,
通过拆项,可以发现该贡献即为x[i]*h[i]*sigma(j=1...i-1,h[j])-h[j]*sigma(j=1...i-1,x[j]*h[j]).
然后预处理一下前缀和就行了---------时间复杂度O(dnlogn).
其实我不是很懂为什么hr说这题是计算几何啊? Interesting....
Code:
#include <bits/stdc++.h>
#define ll long long
#define mod 1000000009ll
using namespace std;
struct node
{ll h,p[5];
}t[300005];
ll p1[300005],p2[300005];
int n,d;
inline bool cmp(node a,node b)
{return a.p[0]<b.p[0];}
int main (){
int i,j;
scanf ("%d%d",&n,&d);
for (i=1;i<=n;i++)
{scanf ("%lld",&t[i].h);
for (j=1;j<=d;j++)
{scanf ("%lld",&t[i].p[j]);}
}
ll ans=0;
for (j=1;j<=d;j++)
{for (i=1;i<=n;i++)
{t[i].p[0]=t[i].p[j];}
sort(t+1,t+n+1,cmp);
for (i=1;i<=n;i++)
{ans+=(((t[i].p[0]*t[i].h)%mod)*p1[i-1])%mod;ans%=mod;
ans-=((t[i].h*p2[i-1])%mod);ans%=mod;
if (ans<0) {ans+=mod;}
p1[i]=p1[i-1]+t[i].h;p1[i]%=mod;
p2[i]=p2[i-1]+t[i].p[0]*t[i].h;p2[i]%=mod;
}
}
printf ("%lld",ans);
return 0;
}