一、题意
一个1...n的序列。(n<=100000)
有4中指令:
1 X Y 表示把X移动到Y的左边
2 X Y 表示把X移动到Y的右边
3 X Y 表示交换X和Y的位置
4 表示反转序列
输出最终序列的奇数位上的数字和,下标从1开始计算。
二、解析
用列表list模拟。
主要是要维护每个元素所在的位置,因此需要维护一个存放迭代器的pos[maxn]数组。
反转序列不需要真的反转,只需要用一个bool变量标记即可,同时注意左右的含义要根据这个标记进行变换。
三、代码
#include <iostream> #include <list> #include <iterator> using namespace std; const int maxn = 100000 + 5; list<int> lst; list<int>::iterator pos[maxn]; int kase = 1; int main() { int n, q; while(cin >> n >> q) { lst.clear(); for(int i = 1; i <= n; i ++) pos[i] = lst.insert(lst.end(), i); bool rev = 0; while(q --) { int ord, x, y; cin >> ord; if(rev) { if(ord == 1) ord = 2; else if(ord == 2) ord = 1; } switch (ord){ case 1: cin >> x >> y; lst.erase(pos[x]); pos[x] = lst.insert(pos[y], x); break; case 2: cin >> x >> y; lst.erase(pos[x]); pos[x] = lst.insert(next(pos[y]), x); break; case 3: cin >> x >> y; iter_swap(pos[x], pos[y]); swap(pos[x], pos[y]); break; case 4: rev = !rev; } } if(rev) lst.reverse(); long long ans = 0; bool odd = 1; for(int num : lst) { if(odd) ans += num; odd = !odd; } cout << "Case " << kase ++ << ": " << ans << endl; } }
四、归纳
- 从这一题可以发现,insert操作不会破坏其它元素的迭代器,只是会改变迭代器的前后关系而已,通过insert的返回值为新元素的迭代器这一点,就可以很清晰地保持迭代器逻辑的完好。
- iter_swap()交换两个迭代器所指向的值
- 通过标记法来避免不必要的操作,如本题的反转操作。