На последнем контесте была задача D. Кай и снежинки. В разборе написано, что вполне подойдет решение в каждой вершине сливать сеты ее потомков.
Очевидно, что худший тест — это просто цепь из 300000 вершин. Тогда получается, что в каждой вершине будет 1, 2, 3,..., 300000 элементов в сете. Всего элементов (арифм. прогрессия) 300000 * 300000 / 2 ~= 45 * 10^9.
Это катастрофически много. Когда я попытался именно сохранить все эти сеты, то, разумеется, получил ML. Однако, если написать как в разборе, то есть просто запуститься рекурсивно из корня и постепенно получать ответ для него (не сохраняя сами сеты), то получим Accepted.
Так вот по сути же выделяем под те же 45 * 10^9 интов. Единственное, что приходит в голову, то что сет после выполнения функции чистит за собой память, которую потребовал в ходе выполнения этой функции, и в последствии может снова использовать ее же.
1) Подскажите, это правда так?
Грубо говоря, есть цикл for (int i = 0; i < 100000; i++) { set a; a.insert(3); }
Правда ли, что потребуется памяти столько, сколько необходимо на одну итерацию? Я просто раньше думал, что выделяется всегда абсолютно новая область памяти. Помогите разобраться, пожалуйста.
set a — локальная переменная, видная только в блоке после цикла фор. Как только область видимости этой переменной заканчивается, она уничтожается и вызывается деструктор. Надо смотреть как у сета написан деструктор. Ну скорее всего он должен все очищать.
А codeforces как оценивает потребляемую память? Может ли этот цикл выполняться 1е15 раз(если не брать в расчет ТЛ)? Или получу вердикт ML?
можно хоть сколько да. вот смотри, например такой код (основной код в функции солв) в запуске на кф и у меня локально выводит два одинаковых адреса. т.е он и в первый и во второй раз разместил переменную в одном и том же месте.
Круто! Я раньше думал, каждое выделение памяти засчитывается как новое. Спасибо!
Если ты будешь делать так, как в разборе, то каждая вершина будет добавлена в какой-либо сет О(лог н) раз (смотри доказательство ранговой эвристики), а значит, вся прога по памяти О(н лог н). Клёво.
В вашем примере, даже если считать суммарное кол-во выделенной памяти, её все равно не квадрат, а nlogn (а иначе бы был TL все равно, вы просто не успевали бы потрогать всю выделенную память)
И да, вы TL получали, а не ML до изменения