Jeśli ustalimy rozmiary podzbiorów
Możemy zatem najpierw posortować listy, zrobić dla nich sumy prefiksowe,
a następnie przeiterować się w czasie
const int N = 110000; int n; double a[N],b[N]; double pa[N],pb[N]; int main() { scanf("%d",&n); REP(i,n) scanf("%lf%lf",&a[i],&b[i]); sort(a,a+n,greater<double>()); sort(b,b+n,greater<double>()); REP(i,n) pa[i+1] = pa[i] + a[i]; REP(i,n) pb[i+1] = pb[i] + b[i]; double ans = 0; REP(an,n+1) REP(bn,n+1) { double cost = min(pa[an], pb[bn]) - (an + bn); ans = max(ans, cost); } printf("%.4lf\n", ans); }
Zobaczmy, jak może się realizować minimum
Tak więc obsługa tych przypadków zajmie czas
REP(an,n+1) { int bn = lower_bound(pb, pb+n+1, pa[an]) - pb; if (bn <= n) { ans = max(ans, pa[an] - (an + bn)); } } REP(bn,n+1) { int an = lower_bound(pa, pa+n+1, pb[bn]) - pa; if (an <= n) { ans = max(ans, pb[bn] - (an + bn)); } }