主页
最近更新
P5381 题解
最后更新于 2025-05-01 18:38:15
作者
EuphoricStar
分类
题解
题解
P5381
复制 Markdown
更新文章内容
首先特判 $a_i = 0$,然后: $\begin{aligned} f_k(x) & = \sum\limits_{i = 1}^k |a_i x + b_i| \\ & = \sum\limits_{i = 1}^k a_i |x + \frac{b_i}{a_i}| \end{aligned}$ 默认 $a_i > 0$,若不满足则 $a_i, b_i$ 同时取相反数即可。 然后这个东西就变成了,数轴上 $-\frac{b_i}{a_i}$ 位置上有 $a_i$ 个点,找一个点使这个点到所有点的距离最小。 根据小学奥数,取所有 $-\frac{b_i}{a_i}$ 的中位数(设为 $p$)最优。然后把 $p$ 代入上面式子,拆绝对值即可。 使用树状数组求中位数和维护 $\sum a_i, \sum b_i$,复杂度 $O(n \log n)$。 ```cpp // Problem: P5381 [THUPC2019] 不等式 // Contest: Luogu // URL: https://www.luogu.com.cn/problem/P5381 // Memory Limit: 500 MB // Time Limit: 3000 ms // // Powered by CP Editor (https://cpeditor.org) #include <bits/stdc++.h> #define pb emplace_back #define fst first #define scd second #define mkp make_pair #define mems(a, x) memset((a), (x), sizeof(a)) using namespace std; typedef long long ll; typedef double db; typedef unsigned long long ull; typedef long double ldb; typedef pair<ll, ll> pii; struct frac { ll x, y; frac(ll a = 0, ll b = 1) { if (b < 0) { a = -a; b = -b; } x = a; y = b; } }; inline bool operator < (const frac &a, const frac &b) { return a.x * b.y < a.y * b.x; } inline bool operator == (const frac &a, const frac &b) { return a.x * b.y == a.y * b.x; } const int maxn = 500100; ll n, tot; frac lsh[maxn]; struct node { ll a, b; } a[maxn]; struct BIT { ll c[maxn]; inline void update(int x, ll d) { for (int i = x; i <= tot; i += (i & (-i))) { c[i] += d; } } inline ll query(int x) { ll res = 0; for (int i = x; i; i -= (i & (-i))) { res += c[i]; } return res; } inline int kth(ll k) { ll s = 0; int p = 0; for (int i = 18; ~i; --i) { if (p + (1 << i) <= tot && s + c[p + (1 << i)] < k) { s += c[p + (1 << i)]; p += (1 << i); } } return p + 1; } } t1, t2; void solve() { scanf("%lld", &n); for (int i = 1; i <= n; ++i) { scanf("%lld", &a[i].a); } for (int i = 1; i <= n; ++i) { scanf("%lld", &a[i].b); if (a[i].a < 0) { a[i].a = -a[i].a; a[i].b = -a[i].b; } if (a[i].a) { lsh[++tot] = frac(-a[i].b, a[i].a); } } sort(lsh + 1, lsh + tot + 1); tot = unique(lsh + 1, lsh + tot + 1) - lsh - 1; ll s = 0, r = 0; for (int i = 1; i <= n; ++i) { if (a[i].a) { int k = lower_bound(lsh + 1, lsh + tot + 1, frac(-a[i].b, a[i].a)) - lsh; t1.update(k, a[i].a); t2.update(k, a[i].b); } else { r += abs(a[i].b); } s += a[i].a; int t = t1.kth((s + 1) / 2); frac p = lsh[t]; db res = t1.query(t) * (1. * p.x / p.y) + t2.query(t); res += -(t1.query(tot) - t1.query(t)) * (1. * p.x / p.y) - (t2.query(tot) - t2.query(t)); printf("%.6lf\n", res + r); } } int main() { int T = 1; // scanf("%d", &T); while (T--) { solve(); } return 0; } ```
Loading...
点赞
2
收藏
0