Codeforces 429D Tricky Function(平面最近点对)

题目链接  Tricky Function

$f(i, j) = (i - j)^{2} + (s[i] - s[j])^{2}$

把$(i, s[i])$塞到平面直角坐标系里,于是转化成了平面最近点对问题。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)

typedef long long LL;

const int N = 100010;

struct Point{
	LL x, y;
	void scan(){ scanf("%lld%lld", &x, &y);}
} p[N], q[N];

int n;
LL c[N];
LL s;

bool cmp_x(const Point &a, const Point &b){ 
	return a.x < b.x;
}
bool cmp_y(const Point &a, const Point &b){
	return a.y < b.y;
}

LL dist(const Point &a, const Point &b){ 
	return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}


LL work(int l, int r){
	if (r == l) return 9e18;
	if (r - l == 1) return dist(p[l], p[r]);
	if (r - l == 2) return min(min(dist(p[l], p[r]), dist(p[l + 1], p[r])), dist(p[l], p[l + 1]));
	int mid = (l + r) >> 1, cnt = 0;
	LL ret = min(work(l, mid), work(mid + 1, r));

	rep(i, l, r) if (p[i].x < p[mid].x + sqrt(ret) && p[i].x > p[mid].x - sqrt(ret)) q[++cnt] = p[i];
	sort(q + 1, q + cnt + 1, cmp_y);
	rep(i, 1, cnt - 1) rep(j, i + 1, cnt){
		if ((q[j].y - q[i].y) * (q[j].y - q[i].y) > ret) break;
		ret = min(ret, dist(q[i], q[j]));
	}

	return ret;
}

int main(){

	scanf("%d", &n);
	rep(i, 1, n) scanf("%lld", c + i);
	rep(i, 1, n){
		s += c[i];
		p[i] = {i, s};
	}
	sort(p + 1, p + n + 1, cmp_x);
	printf("%lld
", work(1, n));
	return 0;

}

  

原文地址:https://www.cnblogs.com/cxhscst2/p/8016415.html