Задача Очередь в магазине не проходит по времени
Задача E. Очередь в магазине Имя входного файла: стандартный ввод Имя выходного файла: стандартный вывод Ограничение по времени: 1 секунда Ограничение по памяти: 256 мегабайт В одном известном магазине случилась распродажа, однако администрация не учла одну проблему: в магазине всего одна касса! Сразу после начала распродажи возле кассы организовалась длинная очередь. Никто не любит очереди, поэтому у покупателей постепенно возрастает уровень агрессии. От вас требуется рассмотреть процесс продвижения очереди. Могут происходить события трёх типов:
- В конец очереди встал человек с уровнем агрессии a;
- Первый человек в очереди начал ругаться с кассиром, в результате чего уровень его агрессии увеличился на x, а уровень агрессии каждого из остальных людей в очереди (если в очереди стоит не один человек) увеличился на y;
- Первый человек в очереди оплатил покупку и ушёл из магазина. От вас требуется обработать N событий. Будем считать, что изначально очередь пуста. Так как администрация магазина заботится о своей репутации, им важно знать, насколько агрессивными их покупатели уходят из магазина. Поэтому для каждого события третьего типа нужно определить уровень агрессии человека, который ушёл из магазина.
Формат входных данных В первой строке записано одно число N — количество событий (2 6 N 6 300000). В каждой из следующих N строк содержится описание очередного события: • 1 a, если произошло событие первого типа; • 2 x y, если произошло событие второго типа; • 3, если произошло событие третьего типа. Для всех событий верно, что 1 6 a, x, y 6 109 . Гарантируется, что события второго и третьего типов происходят только в том случае, если в очереди есть хотя бы один человек. Также гарантируется, что после N событий в очереди не останется ни одного человека. Возможны случаи, когда первый человек в очереди несколько раз подряд ссорится с кассиром. Формат выходных данных Для каждого запроса третьего типа выведите одно число — уровень агрессии человека, который ушёл из магазина. Каждое число следует выводить на отдельной строке. Пример
стандартный ввод
8
1 4
1 2
2 6 1
3
2 10 20
1 1
3
3
стандартный вывод
10
13
1
Замечание
Сначала в очередь встали два человека с уровнями агрессии 4 и 2 соответственно. Затем первый человек поссорился с кассиром, после чего уровни агрессии людей стали равны 10 и 3. После этого первый человек ушёл из очереди, а второй поссорился с кассиром. Теперь уровень его агрессии равен 13. Затем в очередь встал человек с уровнем агрессии 1, после чего оба человека ушли из магазина.
Решал с помощью этого
Получился такой код:`
#include <iostream>
#include <vector>
using namespace std;
int main(){
long d = 0;
vector <long> queue;
int n, value, x, y;
cin >> n;
for(; n > 0; n--){
char command;
cin >> command;
switch(command){
case '1':
cin >> value;
queue.push_back((value - d));
break;
case '2':
cin >> x >> y;
d += y;
queue[0] += (x - y);
break;
default:
cout << (queue[0] + d) << endl;
queue.erase(queue.begin());
}
}
}
Но он не проходит по времени Подскажите, как его можно оптимизировать?`
UPD1:
Ответ выше помог, на ещё одни тест продвинулся, но всё ещё не хватает скорости
#include <iostream>
#include <deque>
using namespace std;
int main(){
long d = 0;
deque <long> queue;
int n;
cin >> n;
for(; n > 0; n--){
char command;
cin >> command;
switch(command){
case '1':
int value;
cin >> value;
queue.emplace_back(value - d);
break;
case '2':
int x, y;
cin >> x >> y;
d += y;
queue[0] += x - y;
break;
default:
cout << (queue.front() + d) << endl;
queue.pop_front();
}
}
}
UPD2 Пошёл по совету, сделал с переменной фронт
#include <iostream>
#include <vector>
using namespace std;
int main(){
long d = 0, front = 0;
vector <long> queue;
int n;
cin >> n;
for(; n > 0; n--){
char command;
cin >> command;
switch(command){
case '1':
int value;
cin >> value;
queue.emplace_back(value - d);
break;
case '2':
int x, y;
cin >> x >> y;
d += y;
queue[front] += x - y;
break;
default:
cout << (queue[front] + d);
++front;
}
}
}
Как и было предложено, реализовал всё на деке. Не знаю, что можно изменить?
UPD3:
Продвижения не стало, на данный момент быстрее всего работает следующий код:
#include <iostream>
#include <deque>
using namespace std;
int main(){
long d = 0;
deque <long> queue;
int n;
cin >> n;
for(; n > 0; n--){
char command;
cin >> command;
switch(command){
case '1':
int value;
cin >> value;
queue.emplace_back(value - d);
break;
case '2':
int x, y;
cin >> x >> y;
d += y;
queue[0] += x - y;
break;
default:
cout << (queue[0] + d) << endl;
queue.pop_front();
}
}
}
На последнем проходящем тесте(32 / 35) он показывает 0.568 с
Ответы (2 шт):
Медленно работает queue.erase(queue.begin());. Удаление элемента из начала вектора приводит к копированию всех элементов вектора на одну позицию влево. Если вектор длинный, это займёт заметное время. Замените вектор на дек (deque) и обработку поменяйте на методы дека (push_back, pop_front).
Ясно же написано: заведем некоторую переменную d, изначально равную нулю, в которой мы будем накапливать некоторое значение агрессивности, которое нужно прибавить ко всем людям в очереди Ваш код вообще не рабочий, потому что в Case 2 вы изменяете только первый элемент очереди, а нужно изменять все элементы.
