https://ac.nowcoder.com/acm/contest/22669/K
小技巧
- 遍歷list且最後一個元素後沒有多餘空格
for (auto it = mylist.begin(); it != mylist.end(); ++it) {
if (it != mylist.begin()) printf(" ");
printf("%d", *it);
}
- 學會使用rbegin() reng()反向遍歷容器
rbegin() 和 end() 在使用上的主要區別在於它們迭代的方向不同。具體來說:
rbegin() 返回一個 反向迭代器,它指向容器的最後一個元素,迭代的方向是 從尾到頭。
end() 返回一個 正向迭代器,它指向容器的最後一個元素的 下一個位置,迭代的方向是 從頭到尾。
區別詳解
rbegin() 和 rend()(反向迭代):
rbegin() 返回指向容器最後一個元素的反向迭代器,rend() 返回指向容器第一個元素之前的位置的反向迭代器。
反向迭代器使你可以從容器的最後一個元素開始向前遍歷。
begin() 和 end()(正向迭代):
begin() 返回指向容器第一個元素的迭代器,end() 返回指向容器最後一個元素之後的迭代器。
正向迭代器是從容器的第一個元素開始向後遍歷。
- 對於多次反轉列表,考慮使用reversed標誌,減少重複反轉,實現“懶反轉”。本題如果按部就班地反轉,會超時
#include <bits/stdc++.h>
std::list<int> mylist;
bool reversed = false; // 用於記錄當前的順序是否被反轉
int main() {
int n, m, a, op;
scanf("%d %d", &n, &m);
while (m--) {
scanf("%d", &op);
if (op == 1) { // 從前面插入
scanf("%d", &a);
if (reversed) {
mylist.push_back(a); // 如果當前被反轉了,則從後面插入
} else {
mylist.push_front(a); // 正常順序下從前面插入
}
} else if (op == 2) { // 從前面刪除
if (reversed) {
mylist.pop_back(); // 當前被反轉,從後面刪除
} else {
mylist.pop_front(); // 正常順序下從前面刪除
}
} else if (op == 3) { // 從後面插入
scanf("%d", &a);
if (reversed) {
mylist.push_front(a); // 被反轉後從前面插入
} else {
mylist.push_back(a); // 正常順序下從後面插入
}
} else if (op == 4) { // 從後面刪除
if (reversed) {
mylist.pop_front(); // 被反轉後從前面刪除
} else {
mylist.pop_back(); // 正常順序下從後面刪除
}
} else if (op == 5) { // 翻轉序列
reversed = !reversed; // 只修改標誌位,不真正翻轉序列
} else if (op == 6) { // 輸出當前元素個數和順序
printf("%zu\n", mylist.size());
if (reversed) {
for (auto it = mylist.rbegin(); it != mylist.rend(); ++it) {
if (it != mylist.rbegin()) printf(" ");
printf("%d", *it);
}
} else {
for (auto it = mylist.begin(); it != mylist.end(); ++it) {
if (it != mylist.begin()) printf(" ");
printf("%d", *it);
}
}
printf("\n");
} else if (op == 7) { // 排序
mylist.sort(); // 直接排序,因為 list 的 sort 內部實現是穩定的 O(n log n)
if (reversed) {
mylist.reverse(); // 如果當前被反轉,需要再反轉回來
}
}
}
return 0;
}