Решение задачи Построение массива с Codeforces
С пояснением   Просмотров: 1216
Выбирается максимальный по длине подмассив (последовательный подотрезок), состоящий только из нулей, среди всех таких отрезков выбирается самый левый;
Пусть этот отрезок равен [l;r]. Если r−l+1 нечетно (не делится на 2), то присваивается a[l+r2]:=i (где i — номер текущего действия), иначе (если r−l+1 четно) присваивается a[l+r−12]:=i.
Рассмотрим массив a длины 5 (изачально a=[0,0,0,0,0]). Тогда он меняется следующим образом:
Сначала мы выбираем отрезок [1;5] и присваиваем a[3]:=1, таким образом a становится равен [0,0,1,0,0];
затем мы выбираем отрезок [1;2] и присваиваем a[1]:=2, таким образом a становится равен [2,0,1,0,0];
затем мы выбираем отрезок [4;5] и присваиваем a[4]:=3, таким образом a становится равен [2,0,1,3,0];
затем мы выбираем отрезок [2;2] и присваиваем a[2]:=4, таким образом a становится равен [2,4,1,3,0];
и наконец мы выбираем отрезок [5;5] и присваиваем a[5]:=5, таким образом a становится равен [2,4,1,3,5].
Ваша задача — найти массив a длины n после выполнения всех n действий. Заметьте, что ответ существует и единственен.
Вам необходимо ответить на t независимых наборов тестовых данных.
Пояснение к задаче
Это просто задача на реализацию. Мы можем использовать какой-нибудь вид кучи или же упорядоченного множества, чтобы сохранить все отрезки, которые нам нужны, в нужном нам порядке. Чтобы решить эту задачу на C++ с использованием std::set, мы можем просто переписать компаратор для std::set таким образом:
struct cmp {
bool operator() (const pair
int lena = a.second - a.first + 1;
int lenb = b.second - b.first + 1;
if (lena == lenb) return a.first < b.first;
return lena > lenb;
}
};
А затем просто написать std::set следующим образом:
set
Теперь минимальный элемент этого множества будет означать отрезок, который нам необходимо выбрать. Изначально множество будет содержать только один отрезок [0;n−1]. Допустим, мы выбираем отрезок [l;r] в течение i-го действия. Пусть id=⌊l+r2⌋, где ⌊xy⌋ равно x деленному на y с округлением вниз. Присвоим a[id]:=i, затем, если отрезок [l;id−1] имеет положительную (большую нуля) длину, добавим этот отрезок в множество, и то же самое сделаем с отрезком [id+1;r]. После n таких действий мы получим ответ.
Асимптотика решения: O(nlogn).
Автор: Администратор