350A - TL
Пусть v = min(ai), p = max(ai), c = min(bi). Тогда если max(2 * v, p) < c, то ответ max(2 * v, p). Иначе ответ - 1.
Авторское решение: 4632352
350B - Курорт
В этой задаче достаточно было реализовать следующее. По сути там задан граф, в виде массива предков для каждой вершины. Поскольку у каждой вершины максимум один предок, то для каждой вершины, являющейся отелем запустим такой алгоритм: будем подниматься по предкам prev[v] до тех пор, пока не встретим вершину со степенью исхода большей единицы. Степень исхода лучше посчитать заранее. После всего обновим ответ.
Асимптотика решения O(n) по времени и O(n) по памяти.
Авторское решение: 4632399
350C - Бомбы
Главная идея, это отсортировать все точки в порядке возрастания величины |xi| + |yi|. Дальше будем обрабатывать каждую точку жадно, максимум за шесть ходов. А именно, пусть мы хотим дойти сейчас до точки (x, y). Пусть x ≠ 0. Тогда нам нужно переместиться ровно на |x| в нужном направлении (если x < 0 то по направлению L, x > 0 — R). Аналогично сделаем для y-координаты. Теперь мы пришли в точку (x, y), возьмем в этой точке бомбу, и аналогично вернемся назад. Почему верно сортировать по так называемому манхэттенскому расстоянию? Понятно, что если мы посмотрим на путь, который мы получили, можно заметить, что все точки пути имеют меньшее манхэттенское расстояние, а значит их мы обработаем раньше.
Асимптотика авторского решения
Авторское решение: 4632478
350D - Поиск сов
Будем решать задачу в целых числах. Поэтому всегда будем строить прямую в целых числах. Операцией нормализации прямой будем называть следующее: Пусть у нас есть прямая Ax + By + C. Пусть также g = gcd(A, gcd(B, C)) (gcd(0, 0) = 0).
Если А < 0 (или A = 0 и B < 0), то умножим уравнение на -1 и поделим все коэффициенты на g.
Теперь решение. Будем поддерживать два отображения (map<> на С++, TreeMap(HashMap) на Java) из прямой, в множество точек (некоторые точки могут встречаться несколько раз). В первом отображении в качестве множества точек мы будем хранить левые границы отрезков, во втором правые границы отрезков (в отсортированном виде).
Заранее по каждому отрезку построим прямую, нормализуем ее, и поддержим наши указанные выше множества множества. Далее, для каждого возможного уравнения отсортируем указанные множества.
Теперь переберем две окружности. Проверим, что расстояние между их центрами больше суммы радиусов и что радиусы одинаковы. Пусть мы построили прямую через центры (x1, y1) и (x2, y2). Перпендикулярная ей прямая, проходящая через центр отрезка [(x1, y1), (x2, y2)] будет иметь уравнение A = 2(x1 - x2), B = 2(y1 - y2), C = - ((x1 - x2) * (x1 + x2) + (y1 - y2) * (y1 + y2)). После этого бинарным поиском по множеству точек, соответствующих указанной прямой, найдем две величины: cntL — количество отрезков, у которых левая граница правее ((x1 + x2) / 2, (y1 + y2) / 2) и cntR — количество отрезков, у которых правая граница левее ((x1 + x2) / 2, (y1 + y2) / 2). Тогда к ответу нужно прибавить величину cntV - cntR - cntL, где cntV — количество отрезков соответствующих заданной прямой в отображении.
Итого, решение за .
Код: 4632546
350E - Неверный Флойд
Решение задачи очень простое, главное придумать почему это верно. Будем действовать так: построим граф с максимальным возможным количеством ребер, потом удалим лишнее. Во-первых, если k = = n, то ответ -1. Иначе зафиксируем некоторую помеченную вершину, например a1. Возьмем в наш граф все ребра, кроме ребер вида a1 < - > x, где x — помеченная вершина. Теперь почему так действовать верно. Если алгоритм Валеры работает неверно, значит существуют пара вершин (i, j) такая, что кратчайшее расстояние посчитано неверно. Значит, на кратчайшем пути из вершины i в вершину j есть хотя бы одна не помеченная вершина (причем, что важно, она не должна совпадать ни с i, ни с j. Если бы такой вершины не было, кратчайшее расстояние посчиталось бы верно. Более того, не нарушая общности, будем считать, что кратчайшее расстояние между i и j равно двум, а алгоритм Валеры нашел больше. Далее, для более формального доказательства нужно рассмотреть случаи, в зависимости от того какой тип имеет каждая из вершин (i, j), однако я рассмотрю случай, когда мы получим больше всего ребер, а именно когда и i, и j — помеченные вершины (а их по условию всегда не меньше двух :)). Во-первых, проведем все ребра во между не зафиксированными ребрами. Дальше проведем и из i и из j ребра в не помеченные вершины. После этого проведем из i все ребра в помеченные, кроме вершины j. Понятно, что больше добавлять ребер нельзя, так как иначе алгоритм Валеры посчитает все верно. Таким образом, мы проведем ровно ребер.
Код: 4632600
BONUS Простой бонус. Можете ли вы для аналогичных входных построить граф, где алгоритм Валеры будет работать верно?
А задача B через систему непересекающихся множеств не быстрее будет? Если нет — хочу узнать почему.
Что? При чем тут СНМ не уточните? И так алгоритм линейный. Куда лучше? Считать ведь надо.
Согласен. Мой косяк.
Клевые задачи, спасибо за столь ранний разбор!
UPD: интернет стормозил, два раза отправилось, сорри
Я в D придумал следующее:
Посортим все пары равных по радиусу непересекающихся окружностей по трём параметрам:
1) направление серпера (задаём каким-нибудь тангенсом, например)
2) ориентированное расстояние от (0; 0) до серпера
3) ориентированное расстояние от середины между центрами до перпендикуляра к серперу, проходящего через (0; 0) (на мой взгляд, удобнее брать именно такой, меньше возни с буквами)
Это работает за m * m * log(m).
Затем для каждого отрезка (n) бинпоиском (logm) найдём среди посорченных пар окружностей подотрезок пар окружностей таких, что этот отрезок лежит на серпере к ним. На этом подотрезке есть посорченные середины между центрами окружностей. Найдём количество тех из них, что лежат на нашем отрезке, опять же, бинпоиском (logm). Итого: m * m * logm + n * logm * logm
Кажется, что в первой задаче должно быть max(2 * v, p) < c (вместо max(2 * v, p) > c).
Да спасибо.
For E Bonus: for k>=1, build a star with any marked vertex(i.e. all nodes are connected directly to marked vertex k.),then continue to build extra edges until the number of edges = m.
Proof: it is clear that the maximum value of pair-wise distance of nodes <= 2 in a star. Also, distance = 1 if and only if there is a path directly connecting those two nodes.(even though the two nodes are both unmarked, their distance is defined as 1 if they are directly connected.) If there are no path between two nodes, the marked node will also provide a "island" for them to finish a path with distance 2. therefore the graph is correct.
k=0 is possible if and only if (m==(n*(n-1))) or (m<=n/2)
C can also be solved by sorting based on the values of |x| and |y|. :)
thanks
Hello Sir Why doesn't it work if sort it according to x and y axis
You might have got the solution by now .
But if you didn't then here is how .
Let's consider Bomb positions ( after sorting) = { (-3,-3) ,(-3,-2),(-2,-3) }
So you do the operations to diffuse bomb at position (-3 , -3 ) first . And for this you will have to go either through (-2 , -3) or (-3,-2) which isn't allowed .
PS : You can also change the direction of your path that is you can move to other points to avoid (-2 , -3) or (-3 , -2 ) but again that will require more direction changes which increase the total number of operations .
My solution for C problem in java is similar to author's solution but I am getting Time out for the solution. Don't know where am I doing the heavy operation. My solution id is 4639684
I think it's just because of System.out.println("..");. You can use String builder instead.
Thank you! I tried and it worked. So thanks and lot and Sorry for trying it so late.
does that apply to cout in c++ because I also solved it in the same way and I am getting TLE , here is my submission
Not to cout, but to endl. Use '\n' instead.
ok , thanks :)
i found the statements very hard to understand for example on problem E it sais that the graph shoud not contain any loops, what i get from this is that the graph is a tree , also i couldnt get the statement on problem B . i know my english sux but still...
I couldnt get the statement on problem B too.
Почему в D не заходит такое? Понятно, что для данной пары окружностей подходящие отрезки должны лежать на серединном перпендикуляре к отрезку между центрами и содержать середину этого отрезка. Будем поддерживать отображение из серединных перпендикуляров в середины отрезков между центрами окружностей, для которых он является серединным перпендикуляром. Ну точнее не сами середины, а выберем на каждой прямой начало отсчета и направляющий вектор и будем складывать в соответствующий
vector<int>
координаты на прямой. Теперь переберём отрезки из инпута, для каждого напишем нормализованное уравнение прямой, найдём эту прямую в нашем мапе и прибавим к ответуupper_bound
конца минусlower_bound
начала в соответствующемvector<int>
.Это получает TLE. Если добавлять в мап только те прямые, на которых содержится хотя бы один отрезок, заходит за 592 мс. Как это объяснить? Непонятно почему тлешится без последней оптимизации.
Возможно в первом случае происходит много бесполезных обращений к мапу через [], а ведь если там ничего нет, то создается еще один элемент в мапе, и в результате он разрастается до больших размеров. А во втором случае обращения уже идут только в тем прямым, на которых что то есть и лишние пустые элементы в мапе не создаются и он остается небольшого размера.
Обращений к мапу через [] вообще не происходит. Используются только методы
find
,insert
и итераторы.D is a great problem, I've learned a lot from it. Thx!
Time limit of the problems of the contest has been changed in such a way that everything gets a TLE ... even ac codes .... SPECIALLY PROBLEM 350C :3
Does anyone feel that statement in problem A is not accurate ? In the below statement:
all wrong solutions do not pass the system testing;
my understanding is that there exists a wrong solution that does not pass the system testing,
But as per the solution to the problem, it means that
no wrong solutions pass the system testing;
i.e., all wrong solutions fail the system testing.
i also find it difficult to understand, btw i did even understand the example of input and output