Блог пользователя IlyaCk

Автор IlyaCk, 12 лет назад, По-русски

Извините за боянистое название, но есть задача и тупо не знаю ни с чего начинать, ни к какой теме отнести. Вот, CF100--C codeforces.ru/contest/140/problem/C чем-то частично напомнила -- я и вспомнил да решил спросить старших и более опытных товарищей.

Собственно условие. Точнее говоря, это русский перевод. Что он правильно отображает украинский текст каким я его увидел я проверял несколько раз. Но если кому не трудно -- можно перепроверить. Возможно, украинский текст сам является переводом, но насчёт этого я ничего не знаю.

Оный отборочный тур проходил в начале марта 2011. Играла ли эта задача где-то ещё -- не знаю. Спросить непосредственно жюри именно того тура нельзя, потому что нельзя (такова политическая ситуация в отдельно взятом институте последипломного образования). Спросить участников тех отборов -- пробовал, никто из них не решил, жюри изобразило, будто рассказать могли бы, да некогда.

  • Проголосовать: нравится
  • +6
  • Проголосовать: не нравится

»
12 лет назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится
Сталкивалась с этой задачей до 2011 года (кажется, в Петрозаводске). Если есть жидкость, количество которой больше суммарного количества всех остальных, то нужно просто объединять все в пары с ней. В противном случае нужно действовать жадно (сливать 1-ю со 2-й, 1-ю с 3-й и т.д.), пока такая (самая большая) не появится.
  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится +10 Проголосовать: не нравится
    кажется, эта задача с контеста Андрея Станкевича, но точно из Петрозаводска
  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится +6 Проголосовать: не нравится
    Хмм, а что будет в таком случае:
    4
    4 4 3 1
    • »
      »
      »
      12 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Предлагаю следующий алгоритм:
      Если есть жидкость, количество которой больше равно суммарного количества всех остальных, то нужно просто объединять все в пары с ней,
      Иначе:
      Берём максимум среди всех, если максимумов несколько - берём самый "некачественный", и отмечаем его(не используем в дальнейшем).
      Теперь начинаем сливать все баночки жадно(1 +2, 1 + 3 итд). Сливаем до тех пор, пока сумма оставшихся жидкостей не станет меньшей или равной нашему максимуму. А вот затем - сливаем максимум со всеми оставшимися банками(возможно 1 останется лишняя).

      P.S.: при чём когда идём жадным алгоритмом - сначала проходимся от 1 до положения максимума, а потом от n назад до положения максимума.

      Пока контрпримера не придумал :)
      • »
        »
        »
        »
        12 лет назад, # ^ |
        Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

        4
        4 4 1 3

        Проблему создаёт последнее число 3 которое по-Вашему вроде как вообще не максимум. (Хотя... это ещё как понять то что Вы написали...)

        См. http://www.codeforces.ru/blog/entry/3557#comment-71914

        • »
          »
          »
          »
          »
          12 лет назад, # ^ |
          Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

          На данном тесте мой алгоритм действовал бы так:
          1) сначала выбираем самый "некачественный максимум"
          2) от 1 до этого максимума сливать нечего, значит сливаем с конца, сливаем 3 с 1, получается 4 4 0 2
          3) Теперь сливаем 4 и 2, но учитываем, что нам ннужно, чтобы осталось <=4 банок в сумме, значит из №1 и №4 делаем лишь 1 зелье
          4) Теперь у нас осталось 3 4 0 1, бутылочек типа №2 теперь ровно столько, сколько сумма всех остальных, значит сливаем все с ней.

»
12 лет назад, # |
Rev. 4   Проголосовать: нравится -9 Проголосовать: не нравится
Решается почти так же как С-шка из 100 контеста =)
»
12 лет назад, # |
Rev. 2   Проголосовать: нравится +17 Проголосовать: не нравится

Огромное спасибо natalia за основную идею. Кажется, понял. Но, поскольку ответ явно был не совсем точен в подробностях, на что уже обращено внимание в http://www.codeforces.ru/blog/entry/3557#comment-71902, хочу изложить подробно, как я понял и доделал.

(Многа букф, конечно, но как изложить короче пока не знаю...)

Действовать надо, в зависимости от ситуации, по одной из двух жадных стратегий.

Ситуация А -- количество бутылочек некоторого вида больше-ИЛИ-РАВНО суммарного количества бутылочек всех остальных видов. Стратегия для этого случая -- сливать бутылочки этого максимального по количеству вида со всеми остальными, в порядке возрастания номеров видов. Начав действовать по данной стратегии, так до конца и действуем только по ней.

Ситуация Б -- всё, что не ситуация А. Для этого случая, брать пару видов с наименьшими возможными номерами (изначально -- 1 и 2, в дальнейшем -- первые ненулевые i и j, иначе говоря такие i и j, что \forall k (k<i -> a[k]=0), \forall k (k<j and k!=i -> a[k]=0), где "\forall" -- квантор всеобщности, "->" -- импликация. Сколько штук слить этих двух видов i и j, определяется минимумом из ТРЁХ величин: либо a[i] либо a[j] либо столько, после скольки ситуация превращается из Б в А.

Если произошёл третий из этих вариантов, далее действуем по стратегии ситуации А. В остальных случаях действуем дальше по стратегии ситуации Б, переопределяя i и/или j.

Теперь подробности на тему "как эффективно поддерживать проверку, что ситуация превращается из Б в А". Прочитав входные данные в массив a, пройдём по нему от конца к началу, считая для каждого эл-та сумму от него до конца a[k]+...+a[n]. Все те k, для которых a[k]>a[k+1]+...+a[n], запоминаем -- только они и будут потенциальными кандидатами на роль тех, из-за которых может понадобиться переключиться со стратегии ситуации Б на стратегию ситуации А. Более того, в каждый момент это может быть только самый левый из всех запомненных потенциальных кандидатов (или срабатывает именно он, или не срабатывает никто). Поддерживать кол-во всех ещё не использованных бутылочек -- элементарно. Пусть кол-во всех ещё не использованных бутылочек равно T, текущим самым левым потенциальным кандидатом является номер p (i<j<p). Найдём то количество x сливаний бутылочек видов i и j, при котором ситуация Б превращается в ситуацию А (если это вообще возможно). Это будет минимальное x при котором  T - 2*x - a[p] <= a[p] что равносильно 2*x >= T - 2*a[p], то бишь x = (T - 2*a[p] + 1) div 2. Значит, если (T - 2*a[p] + 1) div 2 <= min(a[i], a[j]), то надо смешать именно столько штук бутылочек видов i и j, а далее действовать по стратегии ситуации А. Иначе, уменьшаем каждый из эл-тов a[i] и a[j] на min(a[i], a[j]), T на 2*min(a[i], a[j]), переопределяем i и j, при необходимости (j==p) переопределяем p как следующее из ранее запомненных.