0w1

CFR 429 D. Tricky Function ( Divide and Conquer, Closest Pair )

Problem - D - Codeforces

題意:
給 A 數列。求 min{ ( j - i )^2 + Sigma( A[ i + 1 .. j ] )^2, 1 ≤ i < j ≤ N }

資料規模:
The first line of input contains a single integer n (2 ≤ n ≤ 100000). Next line contains n integers a[1], a[2], ..., a[n] ( - 1e4 ≤ a[i] ≤ 1e4).

解法:
就是求最近點對距離。
發現自己以前的寫法慢到不行,需要精進一個地方,那就是不做 inplace_merge ( O( N lg N ) ),而是把和 x 的中位數的距離在好的範圍內的點收集起來就好。

時間 / 空間複雜度:
O( N lg N )

其他:
發現很大一部分的人都是用這種解法,覺得不能理解:
http://codeforces.com/contest/429/submission/6593023

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int MAXN = ( int ) 1e5;

int N;
int A[ MAXN ];
ll pfx[ MAXN + 1 ];

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

ll rec_solve( vector< pair< ll, ll > > &pnt, int lb, int rb ){
  if( lb + 1 == rb ) return 1LL << 50;
  int mid = lb + rb >> 1;
  ll mx = pnt[ mid ].first;
  ll res = min( rec_solve( pnt, lb, mid ), rec_solve( pnt, mid, rb ) );
  vector< pair< ll, ll > > interesting;
  for( int i = lb; i < rb; ++i ){
    if( sqr( pnt[ i ].first - mx ) < res ){
      interesting.emplace_back( pnt[ i ] );
    }
  }
  sort( interesting.begin(), interesting.end(),
      [ & ]( pair< ll, ll > i, pair< ll, ll > j ){ return i.second < j.second; } );
  vector< pair< ll, ll > > t;
  for( int i = 0; i < interesting.size(); ++i ){
    if( sqr( interesting[ i ].first - mx ) >= res ) continue;
    for( int j = t.size() - 1; j >= 0; --j ){
      ll dx = interesting[ i ].first - t[ j ].first;
      ll dy = interesting[ i ].second - t[ j ].second;
      if( sqr( dy ) >= res ) break;
      res = min( res, sqr( dx ) + sqr( dy ) );
    }
    t.emplace_back( interesting[ i ] );
  }
  return res;
}

signed main(){
  ios::sync_with_stdio( 0 );
  cin >> N;
  for( int i = 0; i < N; ++i ){
    cin >> A[ i ];
  }
  for( int i = 0; i < N; ++i ){
    pfx[ i + 1 ] = pfx[ i ] + A[ i ];
  }
  vector< pair< ll, ll > > pnt( N );
  for( int i = 1; i <= N; ++i ){
    pnt[ i - 1 ] = make_pair( i, pfx[ i ] );
  }
  sort( pnt.begin(), pnt.end() );
  cout << rec_solve( pnt, 0, N ) << endl;
  return 0;
}