题目链接 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\n", work(1, n)); return 0; }
时间: 2024-10-17 00:53:01