Задача А. Вторая порядковая статистика
Тематика: Сортировка
В задаче требовалось найти минимальный из всех элементов заданной последовательности, которые строго больше минимального во всей последовательности или сообщить, что его не существует. Разумеется, решений может быть очень много, но один из самых простых способов - считать всю последовательность в массив, отсортировать его и вывести первый элемент, не совпадающий с предыдущим. Если все элементы одинаковы, значит второго по величине не существует.
Задача B. Стол для переговоров
Тематика: Симуляция, динамическое программирование
В этой задаче требовалось определить максимальный периметр прямогульника, который не содержит внутри себя единиц. Назовем прямоугольники, не содержащие единиц, допустимыми. Для решения надо было просмотреть все допустимые прямоугольники и выбрать максимальный периметр. Вопрос в том, как перебирать все допустимые прямоугольники. Говорят, что решение "в лоб" с помощью 6 вложенных циклов за 256 проходит по времени. Очевидно, четыремя циклами мы фиксируем углы прямоугольника, а еще двумя проверяем его допустимость. Не совсем очевидно, что такое решение уложится по времени.
Можно было написать более аккуратное решение с помощью динамического программирования за O((n*m)2). Заметим, что прямоугольник с координатами (x1, y1, x2, y2) является допустимым тогда и только тогда, когда допустимыми явлюятся прямоугольники (x1, y1, x2-1, y2), (x1, y1, x2, y2-1) и в клетке (x2, y2) стоит '0'. Таким образом, пересчет допустимости производится за O(1), что суммарно будет происходить за время O((n*m)2), т.е. линейное от количества прямоугольников.
Задача C. Системный администратор
Тематика: Симуляция
В этой задаче требовалось составить связный граф из n вершин, содержащего m ребер, такой, что при удалении вершины v граф перестанет быть связным или сообщить, что такой граф не существует. При этом не должно быть кратных ребер. Очевидно, что связный граф не может существовать, если число ребер меньше, чем n-1. Кроме того, нетрудно видеть, что максимальное число ребер достигается, когда по одну стороны от v находится одна вершина, а по другую - полный граф из оставшихся вершин. Это число равно (n-1)*(n-2)/2+1. Если число ребер лежит в допустимом диапазоне - граф всегда существует. Дальше нужно было аккуратно разместить одну вершину по одну сторону от v (пусть это вершина 1), а с другой стороны построить связный граф с m-1 ребром. Лучше всего это было сделать проведя сначала ребра из v во все остальные, кроме 1, а затем между всеми остальными (кроме 1).
Задача D. Отрезки
Тематика: Метод сканирующей прямой
В этой задаче требовалось вбить наименьшее число гвоздиков в отрезки так, чтобы каждый отрезок касался хотя бы одного гвоздика. Назовем координату конца отрезка событием. Наши события будут двух типов: начало отрезка и конец отрезка. Отсортируем события в порядке возрастания координат. В случае равенства координат раньше будут идти события начала отрезка. Теперь будем смотреть события в соответствии с заданным порядком: если встретили начало отрезка, добавим его номер в список необработанных отрезков. Как только встретили событие конца отрезка, который еще не обработан, вбиваем туда гвоздь и очищаем список (т.е. считаем, что все отрезки из списка обработаны, т.е. прибиты).
Задача E. Схема
Тематика: Теория графов
В задаче E дан ориентированный граф, требовалось сделать его сильно связным, т.е. чтобы каждая вершина была достижима из любой другой, добавив минимальное число ребер. Из формата входных данных неявно следует очень важное условие: у любой вершины есть не более одного исходящего ребра. Значит, начав путь из некоторой вершины мы либо зациклимся, либо нам некуда будет идти. Отсюда следует, что любая компонента связности (обычной) имеет вид либо замкнутого цикла, либо несколько простых путей, входящих в вершину или цикл. Сначала рассмотрим все пути, выходящие из вершин, у которых нет входящих ребер. Проходя, будем красить вершины, пока либо нам некуда будет идти, либо придем в покрашенную вершину. Тогда вершина, из которой мы пошли, будет называться началом, а в которую пришли - концом компоненты.
После этого рассмотрим еще непокрашенные вершины - они точно принадлежат циклам. Началом и концом цикла назовем некоторую вершину, ему принадлежащую. Получили набор компонент, которые надо соединить. Будем соединять циклически: из конца i-й компоненты пустим ребро в начало ((i+1)%k)-й, где k - число компонент. Ответом будет k. Здесь есть исключение: если у нас только одна компонента, формирующая цикл, то ответ 0.
Таким образом каждое ребро мы просмотрим один раз и время работы составит O(n).
Upd:
В задаче E у любой вершины есть исходящее ребро, поэтому нам всегда есть, куда идти, и любая компонента заканчивается циклом.
Говорят, что в задаче B решение с шестью вложенными циклами работает за 30 мс, т.е. с ним нет никаких проблем.
http://acm.mipt.ru/judge/problems.pl?problem=098
В D оказывается достаточно простое решение.
Я ее сделал так:
Нашел максимальное множество непересекающихся отрезков (делается простым ДП). Размер этого множества равен кол-ву вбиваемых гвоздиков.
Далее рассматривал каждый отрезок из этого множества, последовательно пробегал по его точкам, постепенно добавляя каждый отрезок который с ним пересекается. Если в некоторой точке один из отрезков, который пересекается с отрезком из множества, пересекаться перестал, то значит в предыдущую точку нужно было вбить гвоздь и на этом заканчиваем рассмотрение точек этого отрезка.
Фиксируем левую границу (за N видимо), для каждой строки смотрим сколько справа нулей (это мы предпросчитали заранее), и теперь осталось решить задачу о поиске в массиве подмассива, для которого произведение длины на минимальный элемент максимально. А эта задача решается на M с помощью несложных махинаций со стеком.
не совсем понятно, что делать с незакрашенными вершинами...( которые точно относятся а циклу)....
можно немного конкретней ?
3
2 3 1
я наверно ужен надоел, но у меня не проходит 3 тест...уже 3 раза пытался сдать.... не могу понять : что не правильно ?!
может посмотрите ?
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]),b[a[i]]=1;
for (int i=1;i<=n;i++) if (!b[i]){
j=i;
while (a[j]) x=a[j],a[j]=0,j=x;
w[++k].x=i,w[k].y=j;
}
for (int i=1;i<=n;i++) if (a[i]){
j=i;
while (a[j]) x=a[j],a[j]=0,j=x;
w[++k].x=w[k].y=i;
}
if (k==1 && w[1].x==w[1].y) puts("0");else{
printf("%d\n",k);
w[k+1].x=w[1].x,w[k+1].y=w[1].y;
for (int i=1;i<=k;i++) printf("%d %d\n",w[i].y,w[i+1].x);
}
А вы проверяли ее на том тесте, который я написал? У меня, например, она на нем не работает. Немного подебажил, после строки
w[++k].x=w[k].y=i;
оказалось, что w[0].x = 0, w[0].y = 1, w[1].x = 1, w[1].y = 0. Вероятно, несколько равенств в строке и инкремент ведут себя некорректно.
Большое Спасибо за помощь !!! Наконец - то АС . На том тесте,что давали вы, у меня , почему - то , работало.... В общем я исправил
w[++k].x=w[k].y=i;
на
w[++k].x=i , w[k].y=i; и прошло =)
на олимпе с 4 - мя справился быстро, а с этой промучался почти час... Поэтому очень хотелось дорешать ....
Ещё раз, БОЛЬШОЕ СПАСИБО =)
But the tutorial is great, thanks :) I can go fix my E now :D
There's my code for it. It passes 15, but gets RE on Test 22. I'm really not sure why. Tell me if you can find it, and hopefully it helps you with yours!
I really shouldn't have missed that... though I didn't know that a new Thread could get extra stack space. Most interesting.
I've got AC now and I've updated my code :D
its the same as the "largest rectangle in a histogram" problem except now you're looking for maximal perimeter, and you need to do a dp preprocessing
the "largest rectangle in a histogram" solution is here: http://homeofcox-cs.blogspot.com/2010/04/max-rectangle-in-histogram-problem.html
random.johnnyh Can you please elucidate?
I have written this O(m*m*n) solution for problem B https://mirror.codeforces.com/contest/22/submission/54368605 I am unable to think of any better approach. Can you please provide working code for O(m*n) solution. Thanks in Advance.
praveenojha33 Can you please give a short explanation of your code. Thanks in advance!
Do you know about maximum submatrix sum in a 2D matrix using Kadane Algorithm. If not you can watch it here https://www.youtube.com/watch?v=yCQN096CwWM
The problem is same as finding submatrix sum in 2D matrix this can be done using either O(n^4) approach using 2D prefix sum or using Kadane Algorithm in O(n^3). As you know Kadane Algorithm is O(n) and in 2D Kadane Algorithm we divide 2D matrix in n^2 submatrices that is from column (1-1),(1-2),(1-3),(1-4),(2-2),(2-3),(2-4),(3-3),(3-4),(4-4) and then apply kadane Algorithm to find max sum in that rectagular strip.
Почему это решение 2858329 вызывает TL10 ?
Ну если внимательно посмотреть на тест, то можно догадаться, что после выполнения
m -= n - 1
m становится равным нулю, поэтому в дальнейшем--m
будет возвращать -1, -2, ...Наверное, фиксится исправлением
if (--m <= 0) return;
, по крайней мере, TL уже не будет.