Блог пользователя Mlxa

Автор Mlxa, 5 лет назад, По-русски

Задача

Дан массив a из N целых чисел. Для каждого из них надо найти ближайшее большее слева.

Алгоритм со стеком

Будем считать ответы по порядку, слева направо. Поддерживаем стек. Для каждого элемента удаляем из стека все элементы меньшие или равные ему. Затем, если стек не пуст, ответом для текущей позиции будет элемент на вершине стека. Добавляем текущее число в стек.

Алгоритм без стека

Заметим, что ответы для предыдущих чисел полностью задают стек. Уберём его.

Профит

  • Памяти стало в 2 раза меньше.
  • Время уменьшилось на 20% (по данным Ideone.com).
  • Кода тоже стало меньше.

Код обеих версий

const int N = 4e7;
int a[N];
int link[N];
int stack[N];
int ptr = 0;
 
void with_stack() {
	fill_n(link, N, -1);
	for (int i = 0; i < N; ++i) {
		while (ptr > 0 && a[stack[ptr - 1]] <= a[i]) {
			--ptr;
		}
		if (ptr) {
			link[i] = stack[ptr - 1];
		}
		stack[ptr++] = i;
	}
}
 
void without_stack() {
	for (int i = 0; i < N; ++i) {
		int &l = link[i];
		l = i - 1;
		while (l >= 0 && a[l] <= a[i]) {
			l = link[l];
		}
	}		
}

Этот же код на Ideone (можно раскомментировать вызов одной из функций и посмотреть время работы)

  • Проголосовать: нравится
  • +26
  • Проголосовать: не нравится

»
5 лет назад, # |
Rev. 2   Проголосовать: нравится -29 Проголосовать: не нравится

Зачем насчитывать массив link в решении со стэком, если он используется только в решении без стэка? (Решения работают одинаково по памяти если не нужно сохранять ответы)

  • »
    »
    5 лет назад, # ^ |
      Проголосовать: нравится +11 Проголосовать: не нравится

    В link хранятся ответы для каждого из элементов. (В решении со стеком он действительно не нужен, если ответы нужны online)

»
4 года назад, # |
  Проголосовать: нравится +25 Проголосовать: не нравится

Mlxa, красава, золото IATI 2019