1. 程式人生 > >[Hackerrank題目選做] Jim And Challenges

[Hackerrank題目選做] Jim And Challenges

題目大意: 給定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;
}