hdu 4311

直接暴力的话,O(n2),肯定会超时。分解到两个轴上,通过递推求解,O(nlgn)。要理解这种高效求距离的方法。数轴上的某一点到其他点的距离,可通过从小到大或从大到小递推来做。

#include <iostream>
#include <cstdio>
#include <algorithm>
#define ll _int64
using namespace std;
const int maxn=100010;
int x[maxn],y[maxn],rx[maxn],ry[maxn];
ll disx[maxn],disy[maxn];
int n;
ll solve1(int t)
{
	int low=0,high=n,mid;
	while(high-low>0)
	{
		mid=low+(high-low)/2;
		if(x[mid]==t) break;
		if(x[mid]<t) low=mid+1;
		else high=mid;
	}
	return disx[mid];
}
ll solve2(int t)
{
	int low=0,high=n,mid;
	while(high-low>0)
	{
		mid=low+(high-low)/2;
		if(y[mid]==t) break;
		if(y[mid]<t) low=mid+1;
		else high=mid;
	}
	return disy[mid];
}
int main()
{	
	int t;
	cin>>t;
	while(t--)
	{
		scanf("%d",&n);
		int i;
		for(i=0;i<n;i++)
		{
			scanf("%d%d",&rx[i],&ry[i]);
			x[i]=rx[i];y[i]=ry[i];
		}
		sort(x,x+n);//排序使后续递推可以进行
		sort(y,y+n);
		disx[0]=disy[0]=0;
		for(i=1;i<n;i++)
		{
			disx[0]+=x[i]-x[0];
			disy[0]+=y[i]-y[0];
		}
		for(i=1;i<n;i++)
		{
			disx[i]=disx[i-1]+(ll)(x[i]-x[i-1])*i-(ll)(x[i]-x[i-1])*(n-i);
			disy[i]=disy[i-1]+(ll)(y[i]-y[i-1])*i-(ll)(y[i]-y[i-1])*(n-i);
		}
		ll min=0x3f3f3f3f3f3f3f3f;
		for(i=0;i<n;i++)
		{
			ll tem=solve1(rx[i])+solve2(ry[i]);
			if(min>tem) min=tem;
		}
		printf("%I64d\n",min);
	}
	return 0;
}


posted @ 2012-12-27 16:05  LJ_COME!!!!!  阅读(126)  评论(0)    收藏  举报