예제 #1
0
        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);
        }