Time Limit: 20 Sec
Memory Limit: 256 MB
题目连接
codeforces.com/problemset/problem/429/D
Description
You're given an (1-based) array a with n elements. Let's define function f(i, j) (1 ≤ i, j ≤ n) as (i - j)2 + g(i, j)2. Function g is calculated by the following pseudo-code:
int g(int i, int j) {
int sum = 0;
for (int k = min(i, j) + 1; k <= max(i, j); k = k + 1)
sum = sum + a[k];
return sum;
}
Find a value mini ≠ j f(i, j).
Probably by now Iahub already figured out the solution to this problem. Can you?
Input
The first line of input contains a single integer n (2 ≤ n ≤ 100000). Next line contains n integers a[1], a[2], ..., a[n] ( - 104 ≤ a[i] ≤ 104).
Output
Output a single integer — the value of mini ≠ j f(i, j).
Sample Input
4
1 0 0 -1
Sample Output
1
HINT
题意
给你n个数,让你求最小的f(i,j)
f(i,j)=(j-i)^2+(sum[j]-sum[i])^2
其中sum表示前缀和
题解:
简单分析一下,俩平方,就是距离嘛
把所有点都变成(i,sum[i])然后就是找最近点对了,然后我们有几种做法:
1.科学的暴力加剪枝
2.最近点对问题
3.对每一个点进行二分 nlogn感觉非常科学
代码
#include <cstdio> #include <cmath> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <set> #include <vector> #include <sstream> #include <queue> #include <typeinfo> #include <fstream> #include <map> #include <stack> typedef long long ll; using namespace std; //freopen("D.in","r",stdin); //freopen("D.out","w",stdout); #define sspeed ios_base::sync_with_stdio(0);cin.tie(0) #define test freopen("test.txt","r",stdin) #define maxn 2000001 #define mod 10007 #define eps 1e-5 const int inf=0x3f3f3f3f; const ll infll = 0x3f3f3f3f3f3f3f3fLL; inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } //************************************************************************************** struct Point { ll x; ll y; }point[maxn]; int n; int tmpt[maxn]; bool cmpxy(const Point& a, const Point& b) { if (a.x != b.x) return a.x < b.x; return a.y < b.y; } bool cmpy(const int& a, const int& b) { return point[a].y < point[b].y; } ll dis2(int i, int j) { return (point[i].x - point[j].x) * (point[i].x - point[j].x) + (point[i].y - point[j].y) * (point[i].y - point[j].y); } ll sqr(ll x) { return x * x; } ll Closest_Pair(int left, int right) { ll d = infll; if (left == right) return d; if (left + 1 == right) return dis2(left, right); int mid = (left + right) >> 1; ll d1 = Closest_Pair(left, mid); ll d2 = Closest_Pair(mid + 1, right); d = min(d1, d2); int i, j, k = 0; //分离出宽度为d的区间 for (i = left; i <= right; i++) { if (sqr(point[mid].x - point[i].x) <= d) tmpt[k++] = i; } sort(tmpt, tmpt + k, cmpy); //线性扫描 for (i = 0; i < k; i++) { for (j = i + 1; j < k && sqr(point[tmpt[j]].y - point[tmpt[i]].y) < d; j++) { ll d3 = dis2(tmpt[i], tmpt[j]); if (d > d3) d = d3; } } return d; } int main() { scanf("%d", &n); ll sum = 0; for (int i = 0; i < n; ++i) { int x; scanf("%d", &x); point[i].x = i; sum += x; point[i].y = sum; } cout << Closest_Pair(0, n - 1) << endl; return 0; }