【题目链接】
http://codeforces.com/problemset/problem/429/D
【算法】
令Si = A1 + A2 + ... + Ai(A的前缀和)
则g(i,j) = Sj - Si
f(i,j) = (i-j)^2 + (Si - Sj)^2
观察这个式子,我们发现可以用类似于平面最近点对的算法来求解该问题
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 100010 const long long INF = 1e15; int i,n,x; long long sum[MAXN]; struct point { long long x,y; } a[MAXN]; inline bool cmpx(point a,point b) { return a.x < b.x; } inline bool cmpy(point a,point b) { return a.y < b.y; } inline long long dist(point a,point b) { return abs(a.x - b.x) * abs(a.x - b.x) + abs(a.y - b.y) * abs(a.y - b.y); } inline long long Closest_Pair(int l,int r) { int i,j,mid,len = 0; long long d; static point s[MAXN]; if (l == r) return INF; if (l + 1 == r) return dist(a[l],a[r]); mid = (l + r) >> 1; d = min(Closest_Pair(l,mid),Closest_Pair(mid+1,r)); for (i = l; i <= r; i++) { if ((double)abs(a[i].x - a[mid].x) <= (double)sqrt(d)) s[++len] = a[i]; } sort(s+1,s+len+1,cmpy); for (i = 1; i <= len; i++) { for (j = i + 1; j <= len && s[j].y - s[i].y <= sqrt(d); j++) { d = min(d,dist(s[i],s[j])); } } return d; } int main() { scanf("%d",&n); for (i = 1; i <= n; i++) { scanf("%d",&x); sum[i] = sum[i-1] + x; } for (i = 1; i <= n; i++) a[i] = (point){i,sum[i]}; sort(a+1,a+n+1,cmpx); printf("%I64d ",Closest_Pair(1,n)); return 0; }