Stack Overflow на русском Asked by olbutov2003 on December 28, 2020
Необходимо решить на с++ следующую задачу: можно ли отсортировать массив Аrr (по возрастанию), выполнив переворот ровно одного подотрезка (части массива) Аrr? Если да, вывести "yes" и индексы начала подотрезка.
В противном случае вывести "no". Подробнее https://codeforces.com/problemset/problem/451/B.
Мною был создан следующий алгоритм: Во вложенном цикле создаётся частично перевернутый по индексам переворота i и j(которые и перебираются во вложенном цикле) массив. При совпадении полученного таким способом массива Q и заранее отсортированного массива В выводятся индексы i и j. Ниже приведена функция переворота части массива.
Далный алгоритм работает правильно, но на одном из тестов (70+к размер массива) тестировщик выводит превышение лимита времени. Как значительно оптимизировать перебор индексов или функцию переворота части массива для уменьшения времени работы программы?
Функция переворота части массива:
vector<int> reverse(int l, int r, vector<int> A){
for(int i = l;i<=(l+r)/2;i++)
{
swap(A[i],A[l-i+r]);
}
return A;
}
Если существенная оптимизация невозможна прошу привести более быстрый способ решения задачи.
Возможна следющая оптимизация.
Для того, чтобы вывести ответ, не нужно переворачивать массив.
Нужно просто пройтись по нему, и посчитать, сколько раз происходит смена "убывания-возрастания" значений. Это делается сравнением соседних элементов массива.
Тогда если такое изменение происходит 0, 1 или 2 раза - то "да", есть монотонный кусок массива, перевернув который Вы МОЖЕТЕ получить монотонно отсортированный массив. Если таких смен возрастания-убывания больше - уже не сможете.
Но при этом надо проверить дополнительное условие: что внутри мнотонного подотрезка все значения не меньше значений в одной строне от него и не больше значений в другой стороне.
Я надеюсь, что объяснил достаточно понятно.
Если не поможет - напишите в комментариях, я напишу код
Correct answer by S.H. on December 28, 2020
Алгоритм простой.
Код будет примерно такой (C#)
private static void Solve(int[] numbers)
{
int start = 0;
int end = numbers.Length - 1;
while (start < numbers.Length - 1 && numbers[start] < numbers[start + 1])
start++;
while (start > 0 && numbers[start] < numbers[start - 1])
start--;
while (end > 0 && numbers[end] > numbers[end - 1])
end--;
while (end < numbers.Length - 1 && numbers[end] > numbers[end + 1])
end++;
if (end < start) end = start;
swap(numbers, start, end);
for (int i = 0; i < numbers.Length - 1; i++)
{
if (numbers[i] > numbers[i + 1])
{
Console.WriteLine("no");
return;
}
}
Console.WriteLine("yes");
Console.WriteLine("{0} {1}", start + 1, end + 1);
}
Функция переворачивания
private static void swap(int[] arr, int start, int end)
{
while (start < end)
{
int tmp = arr[start];
arr[start] = arr[end];
arr[end] = tmp;
start++;
end--;
}
}
Заодно отправил решение.
Answered by tym32167 on December 28, 2020
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP