【思维】2018-2019 ICPC Northwestern European Regional Programming Contest (NWERC 2018) A. Access Points
2021-08-24 21:23:00
# ACM
题链
题目解析
题中可将 $x,y$ 轴相互独立出来,则需要解决子问题:
给定一个数列 $A$ ,构造一个非递减的序列 $B$,使得 $\sum_{i=1}^{n}(A_i-B_i)^2$ 最小;
考虑其中某一段取值为 $a$ 时,总和 $\sum_{i=l}^{r}(A_i-a)^2$ 最小,则 $a=\frac{\sum_{i=l}^{r}A_i}{(r-l+1)}$,也就是这一段的平均值,也就是将 $A$ 分为许多段,每一段取平均;
其中如果第 $i$ 段的平均值大于第 $i+1$ 段的平均值,则可以将这两段合并;
具体见代码…
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| #include <bits/stdc++.h> using namespace std; #define LL long long #define Pair pair<LL ,LL > #define ls rt<<1 #define rs rt<<1|1 #define PI acos(-1.0) #define eps 1e-13 #define mod 1000000009 #define MAXN 50001 #define MS 100005
int n,m; LL x[MS], y[MS]; struct node{ LL sum,cnt; }; deque<node > Q;
double cal(LL p[],int n){ while(!Q.empty()) Q.pop_back(); for(int i=1;i<=n;i++){ node t = {p[i],1}; while(!Q.empty() && Q.back().sum*t.cnt > t.sum*Q.back().cnt){ t.sum += Q.back().sum; t.cnt += Q.back().cnt; Q.pop_back(); } Q.push_back(t); } double ans = 0; int cc = 1; while(!Q.empty()){ node t = Q.front(); Q.pop_front(); double val = 1.0*t.sum/t.cnt; for(int i=cc;i<=cc+t.cnt-1;i++){ ans += (val-p[i])*(val-p[i]); } cc += t.cnt; } return ans; }
void solve(){ cin >> n; for(int i=1;i<=n;i++){ cin >> x[i] >> y[i]; } double ans = cal(x,n) + cal(y,n); printf("%.9f\n",ans); }
int main() { ios::sync_with_stdio(false);
int ce = 1;
while(ce--) solve(); return 0; }
|
2021-08-24 21:23:00
# ACM