您的位置:首页 > 其它

CodeForces 429D Tricky Function

2016-06-30 17:40 239 查看

题目大意

给出一个长度为N的序列a。

定义

f(i,j)=(i−j)2+g(i,j)2

g(i,j)=∑jk=iak

求最小的f(i,j)

Data Constraint

N≤105

题解

设Sum[i]表示1~i的和。

那么f(i,j)=(i−j)2+(Sum[j]−Sum[i])2

问题变成:求形如(i,Sum[i])点对间的最小距离。

可以分治求解。

时间复杂度:O(NlogN^2)

SRC

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std ;

#define N 100000 + 10
typedef long long ll ;
const ll Inf = 1e13 ;
struct Note {
ll x , y ;
Note ( int X = 0 , int Y = 0 ) { x = X , y = Y ; }
} Point
, Q
;

int n ;
int a
;
ll ans ;

bool cmpx( Note a , Note b ) { return a.x < b.x || ( a.x == b.x && a.y < b.y ) ; }
bool cmpy( Note a , Note b ) { return a.y < b.y ; }

ll Sqr( ll x ) { return x * x ; }

ll Dis2( Note a , Note b ) {
return Sqr( a.x - b.x ) + Sqr( a.y - b.y ) ;
}

ll DIV( int l , int r ) {
ll ret = Inf ;
if ( l == r ) return ret ;
if ( l + 1 == r ) return Dis2( Point[l] , Point[r] ) ;
int mid = (l + r) / 2 ;
ll d1 = DIV( l , mid ) ;
ll d2 = DIV( mid + 1 , r ) ;
ret = min( d1 , d2 ) ;
double d = sqrt( (double)ret ) ;
int k = 0 ;
for (int i = mid ; i >= l ; i -- ) {
if ( Point[mid].x - Point[i].x > (ll)d ) break ;
Q[++k] = Point[i] ;
}
for (int i = mid + 1 ; i <= r ; i ++ ) {
if ( Point[i].x - Point[mid].x > (ll)d ) break ;
Q[++k] = Point[i] ;
}
sort( Q + 1 , Q + k + 1 , cmpy ) ;
for (int i = 1 ; i < k ; i ++ ) {
for (int j = i + 1  ; j <= k && Q[j].y - Q[i].y <= (ll)d ; j ++ ) {
ret = min( ret , Dis2( Q[i] , Q[j] ) ) ;
}
}
return ret ;
}

int main() {
scanf( "%d" , &n ) ;
ll sum = 0 ;
for (int i = 1 ; i <= n ; i ++ ) {
scanf( "%d" , &a[i] ) ;
sum += a[i] ;
Point[i].x = i ;
Point[i].y = sum ;
}
sort( Point + 1 , Point + n + 1 , cmpx ) ;
printf( "%lld\n" , DIV( 1 , n ) ) ;
return 0 ;
}


以上.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  codeforces