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

Автор Egor, 14 лет назад, По-русски
10 октября в 11:00 MSD состоится очередной этап Открытого кубка. Всем удачи!
  • Проголосовать: нравится
  • +22
  • Проголосовать: не нравится

14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
У кого-нибудь возникали проблемы с TL в задаче K на Java. Решал её за : извлекал из TreeSet максимум. В TreeSet была пара (long long, int). TL.

Переписал на С++ с multiset. Accept. Кто-нибудь таким образом сдал её на Java?


  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    У меня аналогичная ситуация
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Вот тут возникает вопрос: что мешало организатором сделать ограничение n, k ≤ 100000. При 100000 гарантированно зашло бы при  таком TL. 
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Я написал линию, но и ее пришлось немного оптимайзить. Все было жестко :)
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Мы написали один n log n - не прошло. Другой (более быстрый) - не прошло. Линию - и тоже не прошло. Оказалось, какой-то "добрый" человек сделал один тест с огромной кучей мелких тесткейсов, и тормозил cout long long'а. Я конечно понимаю, что быстродействие потоков ввода/вывода - важная тема, но имхо такой тест - полный неадекват (тем более когда надо выводить long long, а printf'ом это нельзя сделать компиляторонезависимо).
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      У меня с L была подобная проблема. Arrays.fill(was,false) и TL. Меняю на цикл до N и ACC.
      • 14 лет назад, # ^ |
          Проголосовать: нравится +5 Проголосовать: не нравится

        Ну это-то понятно, что запрещало сделать 10^4 тестов, вот поэтому и TL. Ты же с увы много пишешь, там такое вообще вроде бы чуть не в каждой задаче :)

        Да и с выводом - боян же. cout тормозной, printf непереносимый. Мы сразу ручной вывод int64 писали в тех задачах, где боялись за TL.

        • 14 лет назад, # ^ |
            Проголосовать: нравится +5 Проголосовать: не нравится
          Были проблемы с new на каждом шаге. Сейчас все объекты, если можно, создаю до цикла обработки тестов. А вот с fill косяков как-то не было. :) Видимо, теперь буду fill-ить тоже ровно столько сколько нужно :)
        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Вывод конечно боян, но имхо тесткейсы должны использоваться по своему прямому назначению, а не для генерации дополнительной "пары приколов" в задаче.
          • 14 лет назад, # ^ |
              Проголосовать: нравится +3 Проголосовать: не нравится
            Пожалуйста не минусуйте, мне правда непонятно

            Я хотел узнать прямое назначение тесткейсов. Просто у меня проблемы с тесткейсами обычно связаны с тем, что в задаче нет указания на количество тесткейсов, а решение, работающее нужное время на одном валится, когда их штук 20. Это как бы очень противно бывает. А в этой олимпиаде в тесткейсах было написано до скольки они и сразу было очевидно, что пройдет, а что нет. И вдруг я узнаю, что это как раз плохая практика, а то, что выше - хорошая. Соответственно вопрос - почему?
            • 14 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится
              Вообще конечно лучше разделение на отдельные тесты безо всяких тесткейсов. Однако на ACM'овских олимпиадах исторически сложилось, что есть один тест с тескейсами внутри, поэтому вполне разумно давать на контестах задачи в таком формате, большая часть команд ведь к ICPC готовится. Но там тесткейсы - это не дополнительная возможность подловить решение на какой-нибудь гадости, а просто замена обычным тестам. Поэтому делать тесты с кучей максимальных тесткейсов, с 500000 одинаковыми тесткейсами и т.п. - это не очень хорошо. Насколько я понимаю, на финале такого ни разу не было (поправьте меня, если я вдруг не прав).
            • 14 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится
              Я тоже об этом думал, возможно, одна из причин для такого — если в задаче требуется вывести что-то вроде "Yes"/"No", то без подхода тесткейсов неверное решение может набрать примерно 50% пунктов. Или же может для того, чтобы сгруппировать класс тестов. А может для того, чтобы уменьшить количество тестов.
              Правда, непонятно, зачем тесткейсы давать на не-"Yes"/"No" задачи.
              • 14 лет назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится
                Ну например, чтобы протестить 1000 наборов входных данных при этом не запуская прогу 1000 раз.
              • 14 лет назад, # ^ |
                  Проголосовать: нравится +1 Проголосовать: не нравится
                У нас же все равно тестирование прекращается при первом же неправильном тесте, так что хоть 50, хоть 99 - все равно не будет засчитано.
                Вот в олимпиадах школьников например - да, такой подход оправдан. Но речь сейчас ведь об ICPC.
                ИМХО, объяснение гораздо проще.
                Исторически, программы для тестирования, использовавшиеся (да и сейчас кое-где использующиеся) на финала и некоторых полуфиналах ICPC, насколько я знаю, попросту не поддерживали не тесткейсовое тестирование. Например, если посмотреть хотя бы на UVa, то там выдается просто "Wrong Answer" без указания номера теста, так что можно предположить, что по крайней мере изначально примерно так же все было и там.
                Более того, подозреваю, что прогон тестов по одному - российское изобретение. PCMS2 - выводит номер теста, на котором упало, Timus и SGU - выводят.
            • 14 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится
              Мне близко такое понимание: если в задаче чётко указаны ограничения, то правильным считается решение, которое работает на всех возможных по условию наборах входных данных. Задача жюри при этом — обеспечить как можно более полную и всестороннюю проверку.

              Соответственно, если сказано, что есть t≤1000 тестов, то проверить решение на различных тестах с t=1000 можно и нужно.

              Да и безо всяких мультитестов, если сказано 1≤n≤1000, то в тестах жюри обязательно должны присутствовать тесты и с n=1, и с n=1000.

              Другое дело, когда ограничение на количество тестов не указано. Для меня это чаще всего означает, что имеется в виду проверка в стиле западных контестов ACM ICPC, и ожидаемое количество тестов по умолчанию — “сотни, но не тысячи”, а сами индивидуальные тесты во вводе не подбираются специально для TL, а образуют как можно более полный тестовый набор.

              В последнем случае используется “развитая система умолчаний”, что, на мой взгляд, не очень хорошо — например, потому, что молодые участники могут ниоткуда не знать про эти “сотни, но не тысячи”, и это ставит команды в неравные условия. Чтобы такая проверка была честной, это умолчание должно быть легко найти в правилах конкретного контеста.
          • 14 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится
            Вряд-ли это делалось для "пары приколов", хотя бы потому, что testsys тестирует под виндой при помощи тех же компиляторов, что были доступны на чемпионате СПбГУ, и те, кто писал на си, печатали любимым быстрым способом.
            Для снарковского сервера это не так. Но какой компилятор на сервере, как там выводить long long, насколько быстро работает cout и какие ограничения в задаче - вроде как не является большим секретом, а тест - противоречащим условию.
        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Разве lld не в любых компиляторах работает ожидаемо?
          • 14 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится
            В старых - нет :) Хотя сейчас такие вряд ли попадаются, но неожиданные приколы бывают (особенно на китайских сайтах :) )
            • 14 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится
              Тогда чисто для справки - как там выводится long long через printf?
              • 14 лет назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится
                В старом вижаке - только %I64d работал. Вообще я статистикой не занимался, но за всё время было столько всяческих проблем с этим... Лично мы в команде используем такой подход: если на сервере компилятор MS VC, то выводим %I64d, а иначе - только cout (либо ручной посимвольный вывод).
    • 14 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
      Можно выводить компиляторонеависимо. Я умею 2 способами.

      1) Выводим %lld и пишем в MSVС(во всяком случае тех версий с которыми работал я) которая принимает оба варианта. Ксати маленькие числа на которых скорее всего тестится решение выводятся и в MinGW нормально.
      2) В виндоус гарантируется определение некоторых констант, которые можно использовать чтобы понять где мы на сервере или на локальном компе.

      #if ( _WIN32 || __WIN32__ )
          #define LLD "%I64d"
      #else
          #define LLD "%lld"
      #endif

      После такой куска кода в макросе LLD находится нужный для вывода параметр и вывод выглядит как-то так pintf(LLD"\n",a);
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        В MSVS %lld работает, начиная по-моему с версии 2005.
      • 14 лет назад, # ^ |
        Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
        Эти хаки я знаю, и не назвал бы это нормальными "компиляторонеависимыми" методами. Если уж на то пошло, отдельные умельцы и cout'ом умеют быстро выводить. Исходный коммент был не про великолепие cout'а, а про неадекватное (не соответствующее "духу" идеи тесткейсов и не встречающееся на ICPCшных соревнованиях) использование тесткейсов для того, чтобы заставить заТЛиться вывод (и в качестве отягчающего обстоятельства - в C++ для того чтобы это обойти приходится использовать кривые методы - printf для long long'а).
        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Думаю это сделано не с целью заТЛить вывод а с целью заТЛить какой-нибудь мемсет всего перед каждым тестом. Хотя насколько это нужно тоже вопрос открытый.
          • 14 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится
            Не, мемсет вряд ли пытались поймать, учитывая, что мемсетить тут нечего: в решениях с логарифмом надо чистить только set/priority_queue, в линейном - стек/очередь. Массив можно использовать разве что для хранения считанных чисел/частичных сумм, но его вряд ли кто-то захочет мемсетить.

            Мне не нравится сама идея такого теста, даже если он не был сделан умышленно против cout'а. Ну не для этого тесткейсы нужны, имхо :) К тому же команды привыкнут к таким вот "приколам", а потом на финале будут тратить дополнительное время на защиту от них - и сольют очередным китайцам.
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      А зачем  компиляторонезависимо ?
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Потому что хаки, костыли, #ifdef'ы и прочая муть - это зло :) Но это моё мнение, допускаю, что могут быть и другие позиции по этому вопросу.
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Ввод корректно работающий под MinGW в виндоус некорректно работает под линуксом и наоборот для лонг лонгов. В итоге приходится это как-то обходить либо изменять код перед посылкой.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Наверное, предполагалось, что должны были проходить только решения за O(n).

Но ограничения для этого очень маленькими оказались.

  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Видимо, да. Но на С++ заходит . В любой случае получается фейловая задача. Либо лимит для Java плохо выставлен, либо для C++. 
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      На Java тоже проходит NlogN без проблем если писать двоичный подъём, а не медленный TreeSet/Map.
      "Только О(n)  решения" не предпологалось.
      • 14 лет назад, # ^ |
        Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
        добрые люди, подскажите подробнее как решать K через multiset:)

        сами мы ее решили за NlogN с помощью метода разделяй и властвуй.

        UPD. оказывается ниже уже описано такое решение, вопрос снимается:)
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        А не изврат ли это? На С++ multiset заходил. На Java стандартная структура - не заходила. Опять фейл. :)
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    А как за O(n)?
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Как решать L?
    • 14 лет назад, # ^ |
        Проголосовать: нравится +8 Проголосовать: не нравится
      1. Пометим все вершины, которые достижимы из 1.
      2. Из всех недостижимых вершин запустим dfs и пометим все, которые достижимы из них.
      3. Ответом будут все те, которые были не помечены посла второго шага.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Как решалась D?
  • 14 лет назад, # ^ |
      Проголосовать: нравится +10 Проголосовать: не нравится
    Есть такое свойство - если для прямой игры для любого 0 функции Гранди из которого есть ходы есть ходы в позицию с функцией Гранди, равной 1, то эта игра сводится к обратному ниму
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Чего-чего? :-D

      Что такое обратный ним - в поддавки? И как именно оно сводится? И как влияет то, что мы может только до n/2 брать?

      • 14 лет назад, # ^ |
          Проголосовать: нравится +6 Проголосовать: не нравится
        Да, поддавки
        Вместо размеров кучек возьмем числа Гранди для игры "не более n/2" (то есть раземр кучки по модулю n / 2 + 1)
        На этих числах порешаем, какую кучку надо добавить, чтобы первый проиграл в обратный ним
        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Мы пробовали брать размеры кучек по модулю n / 2 + 1. Но мы ещё брали, что если все числа <=1 (как в обычном ниме в поддавки), то ответ проксорить с единицей, - это правильно было делать?
          • 14 лет назад, # ^ |
              Проголосовать: нравится +5 Проголосовать: не нравится
            Если все числа Гранди для кучек не больше 1, то нам надо добавить кучку размером 1 если 1ц четное число и 0, если нечетное
            • 14 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится
              Хм. Тогда непонятно, почему wa3 :)
            • 14 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится

              Нет, всё же уточню :)

              Решение прямо такое:

              0) сгенерировать в a_i всю прогрессию как в int64

              1) взять все a_i по модулю n/2 + 1 (обычный модуль - который возвращает от 0 до n/2)

              2) если все числа <=1, то если единичек четное число - вывести 1, иначе 0

              3) иначе проксорить все числа и вывести это

              Неужели точно так же?

              • 14 лет назад, # ^ |
                  Проголосовать: нравится +5 Проголосовать: не нравится
                Да, у меня так же прошло.
                • 14 лет назад, # ^ |
                    Проголосовать: нравится 0 Проголосовать: не нравится
                  Жесть. Тогда ничего не понимаю :)
                  • 14 лет назад, # ^ |
                    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
                    long long ftw?

                    EDIT: у нас была бага в чтении d (которое тоже бывает 64битным), при исправлении на long long зашло.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Как решать  задачи B и P? 
  • 14 лет назад, # ^ |
      Проголосовать: нравится +5 Проголосовать: не нравится
    Вот решение В:
    Сохраним в массиве А[1..2*z] количество пар остановок, с каждым возможным расстоянием d. Посчитаем массив sum[0..2*z], в i-ом элементе которого будет сумма элементов массива А с первого до i-го. Ответ на запрос будет таким: sum[r]-sum[l-1].
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    в задаче B проходил и N ^ 2 logN + K logN
14 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
кто нить может кинуть ссылку на условие задач? или расказать формат inputа в задаче F (про суммы на отрезках)? а то условия не сохранились, а сдать хочеться)
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    http://158.250.33.215/~ejudge/files/opencup/oc8/gp4/chspbioc.html
    Мог бы и сам найти, просто залогинившись в контест (посмотрев id у standing'ов ;))
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      либ я чет не понимаю, либо это ссылка немного не на те условия)) а просто залогинившись в контест ссылка на условие паленая
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Открываю условия - вижу ровно то, что было сегодня на контесте. Может, мы конечно решали не по тем условиям, но как тогда столько задач зашло? :)
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      кстати раз уж ты Илья тут, как делали ее?
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Хоть и не Илья, но расскажу наше решение :)

        sqrt-декомпозицией разобьём всё на sqrt(n) блоков.

        В каждом блоке будем хранить maximum_x - наибольшее x, которым мы красили весь этот блок, и ещё все числа этого блока в порядке сортировки.

        Тогда если поступает запрос присвоения, то во всех блоках, которые попадают в наш отрезок целиком, просто обновляем maximum_x. В двух граничных блоках проходимся и присваиваем значения втупую (за sqrt(n). это можно сделать, не пересорчивая содержимое блока (слиянием за линию двух отсортированных массивов), иначе TL).

        Теперь пусть пришёл запрос поиска суммы. В двух граничных блоках ответим на запрос втупую. Теперь что делать с целыми блоками: в каждом таком блоке нужно найти, сколько элементов <= текущего maximum_x этого блока; для этого очевидное решение - сделать бинпоиск по содержимому блока (как раз для этого мы и поддерживали его содержимое в отсортированном порядке), но это будет лишний log в асимптотике. Поэтому, заметив, что maximum_x всегда только возрастает, будет хранить в каждом блоке указатель на первый элемент, >= maximum_x, и продвигать его вправо когда надо.

        В сумме должно быть N sqrt(N), а не сдали из-за реализационных косяков.

        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          ну собственно мы это и придумали за 20 мин до конца когда уже ушли..))
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Корневой оптимизацией, там всё получилось довольно просто (для каждого отрезка храним его в отсортированном виде а также максимальный x, которым этот отрезок полностью обновляли). Видимо, можно то же самое делать деревом за n log n (или log^2 n, надо подумать), но мы не стали создавать себе дополнительных сложностей для реализации.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Что то никто про задачу С не спрашивает. Мне вот крайне интересно как ее по-человечески решать. Мы в ней заметили извратную закономерность, которую даже не пытались обосновать. В итоге ответ на один тест находится где то за log(X)
  • 14 лет назад, # ^ |
      Проголосовать: нравится +5 Проголосовать: не нравится
    Посмотрим на последовательность Фибоначчи. Пусть до X там уместится N чисел. Известно, что она - худший случай, однако возможно есть и другие худшие случаи. Утверждается, что все они строятся как последовательность Фибоначчи, только на каком-то (одном!) шагу возможно f_{n + 1} = 2 * f_n + f_{n - 1}. Сгенерируем все такие последовательности - все, у которых уместилось N чисел до X, тоже подходят. На один тест тут действительно получается log(X), однако, если погенерить всё заранее и делать аккуратно, то будет log(log(X)). Только этого в задаче уже не требовалось.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Как решить задачу К(о команде) на Паскале? Подкиньте, пожалуйста, кто-нибудь план решения. Спасибо.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    А какая вам разница на каком языке, если нужен только план решения? :) Выше эту задачу уже обсуждали, например, тут (понятно, что при проходе слева направо по удвоенному массиву надо среди последних k частичных сумм выбирать наименьшую и пробовать вычесть из текущей суммы, т.к. все суммы по отрезкам, заканчивающимся в i (i >=k) - это a[i] - a[i - 1], a[i] - a[i - 2], ..., a[i] - a[i - k], где a[i] - сумма первых i чисел удвоенного массива (удвоенного - т.к. там всё циклическое). За O(1) искать минимум позволяет описанная по ссылке структура данных, за O(log n) - куча или декартово дерево).
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
А можно ли зайти в систему не в дорешивание, а в сам контест, чтобы скачать субмит? Какой id подставлять, если так можно?
  • 14 лет назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится
    Да, 10114 для первого и 10124 для второго дивизиона