На вход
программы подается набор операций со стеком. Каждая операция состоит в
добавлении или удалении элемента из стека. После выполнения каждой операции
найдите наименьшее число, которое находится в стеке. Сложите все полученные числа
и получите ответ. Если после некоторой операции стек оказался пуст, то ничего
не прибавляйте к ответу. Если выполнить удаление невозможно, так как стек пуст,
то не выполняйте его.
Вход. Входные данные генерируются в самой программе. На вход
подаются параметры для генерации входной последовательности.
Первое число содержит количество операций n (1 ≤ n ≤ 106) со стеком. Затем следуют четыре
неотрицательных целых числа a, b, c,
x0, не превосходящие
10000.
Для получения входных данных сгенерируем последовательность x.
Первое число в генерируемой последовательности x1. Первое, а также каждое
следующее число вычисляется из предыдущего по формуле:
xi = (a· + b·xi-1 + c) / 100 mod 106,
где '/' – операция целочисленного деления, а 'mod' – остаток
от деления.
Если xi
mod 5 < 2, то необходимо удалить число из стека. В противном случае нужно
добавить в стек число xi.
Выход. Выведите
результирующую сумму.
Пример
входа 1 |
Пример
выхода 1 |
2 0 0 1 81 |
0 |
|
|
Пример
входа 2 |
Пример
выхода 2 |
3 1 1 1 13 |
0 |
структуры
данных - стек
Анализ алгоритма
В задаче
достаточно промоделировать работу со стеком. Если xi mod 5 ≥ 2, то заносить в стек будем не само
очередное значение xi, а
минимум вершины стека и значения xi.
Если стек пустой, то заносим в него xi.
При xi mod 5 < 2
удаляем число из вершины стека. При таком подходе обработки входных данных на
вершине стека всегда будет находиться минимальное значение среди всех обработанных,
но на данный момент еще не удаленных значений xi.
После обработки
очередного значения xi к
результирующей сумме res необходимо
добавить значение, хранящееся в вершине стека.
Реализация алгоритма
Объявим
структуру данных стек.
stack<long
long> s;
Читаем входные
данные.
scanf("%lld %lld %lld %lld %lld",&n,&a,&b,&c,&x);
for(res = i = 0; i < n; i++)
{
В переменной x получаем очередной элемент xi последовательности. В зависимости от значения x mod 5 или кладем в стек минимум
его и значения, находящегося на вершине стека, или удаляем число из вершины
стека.
x = ((a*x*x + b*x + c) / 100) % 1000000;
if (x % 5
< 2)
{
if
(!s.empty()) s.pop();
} else
{
if
(s.empty()) s.push(x);
else
s.push(min(s.top(),x));
}
Если стек не пустой, то прибавляем к
результирующей сумме значение, хранящееся в его вершине.
if (!s.empty()) res += s.top();
}
Выводим ответ.
printf("%lld\n",res);
Реализация стека при помощи статического
массива
Поскольку
количество операций n со стеком не
больше 106, то достаточно использовать стек указанного размера.
#include <stdio.h>
long long
i, n, a, b, c, x, res;
class Stack
{
private:
long long *m;
int topPtr,
size;
void
allocate()
{
m = new long long[size];
topPtr = EmptyStack;
}
public:
enum
{DefaultStack = 1000010, EmptyStack = -1};
Stack()
{
size = DefaultStack;
allocate();
}
Stack(int n)
{
if (!n) n =
DefaultStack;
size = n;
allocate();
}
~Stack()
{
delete[] m;
}
int full(void)
{
return
topPtr + 1 >= size;
}
int empty(void)
{
return
topPtr <= EmptyStack;
}
void push(const long long &Value)
{
if
(!full()) m[++topPtr] = Value;
}
long long pop(void)
{
if
(!empty()) return m[topPtr--];
return 0;
}
long long top(void)
{
if
(!empty()) return m[topPtr];
return 0;
}
};
long long
min(long long
a, long long b)
{
return (a
< b) ? a : b;
}
Stack s;
int main(void)
{
scanf("%lld
%lld %lld %lld %lld",&n,&a,&b,&c,&x);
for(res = i =
0; i < n; i++)
{
x = ((a*x*x + b*x + c) / 100) % 1000000;
if (x % 5
< 2)
{
if
(!s.empty()) s.pop();
} else
{
if
(s.empty()) s.push(x);
else
s.push(min(s.top(),x));
}
if
(!s.empty()) res += s.top();
}
printf("%lld\n",res);
return 0;
}
Реализация стека при помощи динамического
массива
#include <stdio.h>
#include <string.h>
long long
i, n, a, b, c, x, res;
class DynamicArray
{
private:
long long *Storage;
int Size,
Capacity;
public:
DynamicArray(void)
{
Capacity = 10;
Storage = new
long long[Capacity];
memset(Storage,0,sizeof(long long)*Capacity);
Size = 0;
}
DynamicArray(int
Capacity)
{
this->Capacity
= Capacity;
Storage = new
long long[Capacity];
memset(Storage,0,sizeof(long long)*Capacity);
Size = 0;
}
~DynamicArray()
{
delete[]
Storage;
}
int getSize(void)
{
return
Size;
}
int
getCapacity(void)
{
return
Capacity;
}
void Print(void)
{
for(int i = 0; i < Size; i++)
printf("%d
",Storage[i]);
}
void
ensureCapacity(int minCapacity)
{
if
(minCapacity > Capacity)
{
int
newCapacity = (Capacity * 3) / 2 + 1;
if
(newCapacity < minCapacity) newCapacity = minCapacity;
long long *temp = new long long[newCapacity];
memcpy(temp, Storage, Size * sizeof(long long));
delete[]
Storage;
Storage = temp;
Capacity = newCapacity;
}
}
void Pack(void)
{
if (Size
<= Capacity / 2)
{
int
newCapacity = (Size * 3) / 2 + 1;
long long *temp = new long long[newCapacity];
memcpy(temp, Storage, Size * sizeof(long long));
Capacity = newCapacity;
delete[]
Storage;
Storage = temp;
}
}
void Trim(void)
{
int
newCapacity = Size;
long long *temp = new long long[newCapacity];
memcpy(temp, Storage, Size * sizeof(long long));
delete[]
Storage;
Storage = temp;
}
void
SetElement(int index, int
value)
{
if
((index < 0) || (index >= Size)) return;
Storage[index] = value;
}
long long GetElement(int
index)
{
if
((index < 0) || (index >= Size)) return
-1;
return
Storage[index];
}
int Empty(void)
{
return
(Size == 0);
}
void
RemoveAt(int index)
{
if
((index < 0) || (index >= Size)) return;
int
moveCount = Size - index - 1;
if
(moveCount > 0)
{
for(int i = index; i < Size - 1; i++)
Storage[i] = Storage[i+1];
}
Size--;
Pack();
}
void
insertAt(int index, long
long value)
{
if
((index < 0) || (index >= Size)) return;
ensureCapacity(Size + 1);
int
moveCount = Size - index;
if
(moveCount > 0)
{
for(int i = Size - 1; i >= index; i--)
Storage[i+1] = Storage[i];
}
Storage[index] = value;
Size++;
}
void
push_back(long long
Value)
{
ensureCapacity(Size + 1);
Storage[Size] = Value;
Size++;
}
void
pop_back(void)
{
if (Size
== 0) return;
Size--;
Pack();
}
long long back(void)
{
return
Storage[Size-1];
}
};
class Stack
{
private:
DynamicArray m;
public:
Stack()
{
}
int empty(void)
{
return
m.Empty();
}
void push(const long long &Value)
{
m.push_back(Value);
}
void pop(void)
{
if
(!empty()) m.pop_back();
}
long long top(void)
{
if
(!empty()) return m.back();
return 0;
}
};
long long
min(long long
a, long long b)
{
return (a
< b) ? a : b;
}
Stack s;
int main(void)
{
scanf("%lld
%lld %lld %lld %lld",&n,&a,&b,&c,&x);
for(res = i =
0; i < n; i++)
{
x = ((a*x*x + b*x + c) / 100) % 1000000;
if (x % 5
< 2)
{
if (!s.empty())
s.pop();
} else
{
if
(s.empty()) s.push(x);
else
s.push(min(s.top(),x));
}
if
(!s.empty()) res += s.top();
}
printf("%lld\n",res);
return 0;
}
Реализация стека при помощи
связанного списка
#include <stdio.h>
long long
i, n, a, b, c, x, res;
class Stack
{
private:
struct node
{
long long value;
struct node
*next;
};
node *head;
int size;
public:
Stack()
{
size = 0;
head
= NULL;
}
~Stack()
{
while(!empty())
{
node *temp = head;
head = head->next;
delete
temp;
}
}
int empty(void)
{
return
(head == NULL);
}
void push(const long long &Value)
{
node *temp = new
node;
temp->value = Value;
temp->next = head;
head = temp;
}
long long pop(void)
{
if
(!empty())
{
int value
= head->value;
node *temp = head;
head = head->next;
delete
temp;
return
value;
}
return 0;
}
long long top(void)
{
if
(!empty()) return head->value ;
return 0;
}
};
long long
min(long long
a, long long b)
{
return (a
< b) ? a : b;
}
Stack s;
int main(void)
{
scanf("%lld
%lld %lld %lld %lld",&n,&a,&b,&c,&x);
for(res = i =
0; i < n; i++)
{
x = ((a*x*x + b*x + c) / 100) % 1000000;
if (x % 5
< 2)
{
if
(!s.empty()) s.pop();
} else
{
if
(s.empty()) s.push(x);
else
s.push(min(s.top(),x));
}
if
(!s.empty()) res += s.top();
}
printf("%lld\n",res);
return 0;
}
Время работы
программы
Статический
массив |
0.250 секунды |
Динамический
массив |
0.296 секунды |
Динамический
стек на указателях |
0.406 секунды |
Стек при
помощи вектора |
0.421 секунды |
Использование
класса stack из STL |
0.765 секунды |
Java реализация
import
java.util.*;
public class
Main
{
public static void
main(String[] args)
{
Stack<Long> s = new Stack<Long>();
Scanner con = new
Scanner(System.in);
long n =
con.nextLong();
long a = con.nextLong();
long b =
con.nextLong();
long c =
con.nextLong();
long x =
con.nextLong();
long res =
0;
for(int i = 0; i < n; i++)
{
x = ((a*x*x + b*x + c) / 100) % 1000000;
if (x % 5
< 2)
{
if
(!s.empty())
s.pop();
} else
{
if
(s.empty())
s.push(x);
else
s.push(Math.min(s.peek(),x));
}
if
(!s.empty())
res += s.peek();
}
System.out.println(res);
con.close();
}
}