CF 429D
求Min((j-i)^2+(sum(a[i+1]~a[j]))^2
我们发现sum(a[i+1]~a[j])=(pre[j]-pre[i])
那么我们求的即是(j-i)^2+(pre[j]-pre[i])^2
我们把(i,pre[i])抽象成一个点,那么所求即是两点距离
Ans即是平面最近点对距离,分治解决
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> #include<utility> #define x first #define y second using namespace std; typedef long long ll; typedef pair<ll,ll> pi; pi a[100011],ts[100011],que[100011]; int n,i,x; ll ans,pre[100011]; ll dis(pi a,pi b) { return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); } bool cmpy(pi a,pi b) { return a.y<b.y; } void Solve(int l,int r) { int tc,mid,L,R,i,j; ll mx; if(l+1>=r){ if(r==l+1)ans=min(ans,dis(a[l],a[r])); return; } mid=(l+r)/2; Solve(l,mid); Solve(mid+1,r); mx=a[mid].x; tc=0; for(i=mid;i>=l;i--){ if((mx-a[i].x)*(mx-a[i].x)>=ans)break; ts[++tc]=a[i]; } for(i=mid+1;i<=r;i++){ if((mx-a[i].x)*(mx-a[i].x)>=ans)break; ts[++tc]=a[i]; } sort(ts+1,ts+1+tc,cmpy); L=1;R=0; for(i=1;i<=tc;i++){ R++; que[R]=ts[i]; while(L<R&&(que[L].y-que[R].y)*(que[L].y-que[R].y)>=ans)L++; for(j=L;j<R;j++)ans=min(ans,dis(que[j],que[R])); } } int main() { scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d",&x); pre[i]=pre[i-1]+x; a[i].x=i;a[i].y=pre[i]; } ans=1ll<<60; Solve(1,n); printf("%I64d\n",ans); }