private static long SolveFast(long n, long m, List <long> a, List <long> b) { var sortedDays = new SortedSet <Day>(new DayComparer()); for (var i = 0; i < n; i++) { var day = new Day(i, a[i], b[i], 0); sortedDays.Add(day); } var cTotal = 0L; var aTotal = 0L; for (var i = 0; i < n; i++) { cTotal += a[i] * b[i]; aTotal += a[i]; } foreach (var day in sortedDays.ToList()) { cTotal -= day.C; aTotal -= day.A; n--; // C_average_adjusted = C_average * (1 - (M-BALLOON) / A_total) // = C_day - B_day * BALLOON // <=> BALLOON = (C_day - C_average * (1 - M / A_total)) / (C_average / A_total + B_day) var balloonNeeded = n > 0 ? (day.C - cTotal * 1.0 / n * (1 - m * 1.0 / aTotal)) / ((cTotal * 1.0 / n) / aTotal + day.B) : day.A; var balloon = Math.Min((long)Positiv(balloonNeeded), m); if (balloon > 0) { sortedDays.Remove(day); m -= balloon; day.AddBalloon(balloon); sortedDays.Add(day); } } for (var k = m; k > 0; k--) { var day = sortedDays.Max; sortedDays.Remove(day); day.AddBalloon(); sortedDays.Add(day); } var nextSortedDays = new SortedSet <Day>(new NextBalloonDayComparer()); foreach (var day in sortedDays) { if (day.CanRemoveBalloon()) { nextSortedDays.Add(day); } } // switch while (sortedDays.Max.C > nextSortedDays.Min.C + nextSortedDays.Min.B) { var day = sortedDays.Max; sortedDays.Remove(day); nextSortedDays.Remove(day); var nextDay = nextSortedDays.Min; sortedDays.Remove(nextDay); nextSortedDays.Remove(nextDay); day.AddBalloon(); sortedDays.Add(day); nextSortedDays.Add(day); nextDay.RemoveBalloon(); sortedDays.Add(nextDay); if (day.CanRemoveBalloon()) { nextSortedDays.Add(nextDay); } } var res = sortedDays.Max.C; return(res); }