●CodeForces 429D Trick_Function

题链:

http://codeforces.com/problemset/problem/429/D
题解:

分治,最近点对
不难发现g(i,j)=sum[j]-sum[i],
那么f(i,j)=(i-j)²+(sum[j]-sum[i])²
=(i-j)²+(sum[i]-sum[j])²
然后可以把(i,sum[i])看成平面上的点,
那么要求f(i,j)min就转变为了求平面上的最近点对问题。
用分治即可解决。

代码:

#include<bits/stdc++.h>
#define MAXN 100005
#define ll long long
#define INF 0x3f3f3f3f3f3f3f3fll
using namespace std;
struct Point{
	ll x,y;
	bool operator < (const Point &rtm) const {
		return x<rtm.x||(x==rtm.x&&y<rtm.y);
	}
}A[MAXN],B[MAXN];
int N;
ll sum[MAXN];
int idx[MAXN];
ll ABS(ll x){return x<0?-x:x;}
bool cmpx(const Point &a,const Point &b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
bool cmpy(const Point &a,const Point &b){return a.y<b.y||(a.y==b.y&&a.x<b.x);}
ll dis2(Point &a,Point &b){return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
void build_index(){
	map<Point,int>M;
	for(int i=1;i<=N;i++) M[A[i]]=i;
	for(int i=1;i<=N;i++) idx[i]=M[B[i]];
}
ll divide(int l,int r){
	ll ans=INF;
	static int tmpidx[MAXN];
	static Point tmpB[MAXN];
	if(r-l<=3){
		for(int i=l;i<=r;i++) for(int j=i+1;j<=r;j++)
			ans=min(ans,dis2(A[i],A[j]));
		return ans;
	}
	int mid=(l+r)>>1,bl=l,br=mid+1,bnt;
	for(int i=l;i<=r;i++){
		if(idx[i]<=mid) tmpB[bl]=B[i],tmpidx[bl++]=idx[i];
		else tmpB[br]=B[i],tmpidx[br++]=idx[i];
	}
	for(int i=l;i<=r;i++) B[i]=tmpB[i],idx[i]=tmpidx[i];
	ans=min(ans,divide(l,mid));
	ans=min(ans,divide(mid+1,r));
	bnt=l; bl=l; br=mid+1;
	//归并排序
	while(bl<=mid&&br<=r){
		if(cmpy(B[bl],B[br])) tmpB[bnt++]=B[bl++];
		else tmpB[bnt++]=B[br++];
	}
	while(bl<=mid) tmpB[bnt++]=B[bl++];
	while(br<=r) tmpB[bnt++]=B[br++];
	for(int i=l;i<=r;i++) B[i]=tmpB[i];
	
	bnt=1;
	for(int i=l;i<=r;i++) if(ABS(B[i].x-A[mid].x)<=ans)
		tmpB[bnt++]=B[i];
	for(int i=1;i<bnt;i++)
		for(int j=1;j<=6&&i+j<bnt;j++)
			ans=min(ans,dis2(tmpB[i],tmpB[i+j]));
	return ans;
}
int main(){
	scanf("%d",&N);
	for(int i=1;i<=N;i++){
		scanf("%lld",&sum[i]);
		sum[i]+=sum[i-1];
		A[i]=B[i]=(Point){i,sum[i]};
	}
	sort(A+1,A+N+1,cmpx);
	sort(B+1,B+N+1,cmpy);
	build_index();
	ll ans=divide(1,N);
	printf("%lld
",ans);
	return 0;
}

  

原文地址:https://www.cnblogs.com/zj75211/p/8541792.html