题意:
给定N个盒子,分别标号为1~N;有下面4种操作:
“1 X Y” 表示将X移到Y的左边;
“2 X Y” 表示将Y移到Y的右边;
“3 X Y” 表示交换X与Y的位置;
“4” 表示将1~N所有的盒子反序。
要你求经过M次操作之后,所有奇数位置的盒子标号之和。
分析:
前三种操作都是对单个盒子进行操作,第四种操作是对所有盒子进行操作,那么我们首先来考虑第四种情况。
由于只要求所有奇数位置的盒子标号之和,那么可以发现,当N为奇数的时候,将所有盒子逆序,是不会改变此时的所有奇数位置的盒子标号之和的,当N是偶数的时候,不逆序的情况下,求所有偶数位置的盒子标号之和,即所有位置的盒子标号之和 - 所有奇数位置的盒子标号之和,因此,我们对于操作4不进行反序处理,而只是将这种操作标记下来,如果有偶数倍操作4,那么这个时候我再清除标记即可。
那么还有一个问题就是,如果前面出现了奇数倍的操作4,接下来,进行操作1,2的时候,我只需要将操作1变为操作2,操作2变为操作1。比如:
输入如下:
6 4 <<对应的状态>> 1 2 3 4 5 6
4 <<对应的状态>> 6 5 4 3 2 1
1 1 4 <<对应的状态>> 6 5 1 4 3 2
其实可以发现,上面的情况中求得的答案等价于下面这种情况
6 4 <<对应的状态>> 1 2 3 4 5 6
2 1 4 <<对应的状态>> 2 3 4 1 5 6
,操作2的处理也是同理。。
注意:
计数的count注意定义为long long
我还有个疑问,函数返回值为迭代器,为什么不能成功,希望有哥哥帮我解决一下,这样就能减少代码量了
#include <iostream>
#include <list>
using namespace std;
//list<int>::iterator find(int it, list<int> li) {
// list<int>::iterator ite;
// for (ite = li.begin(); ite != li.end(); ite++) {
// if (*ite == it) {
//
// break;
// }
// }
// return ite;
//}
int main() {
int n, m;
while (cin >> n >> m) {
list<int> li;
for (int i = 0; i < n; i++) {
li.push_back(i + 1);
}
long long count = 0;
while (m--) {
int d;
cin >> d;
int x, y;
if (d == 1) {
cin >> x >> y;
list<int>::iterator xx;
for (xx = li.begin(); xx != li.end(); xx++) {
if (*xx == x) {
break;
}
}
list<int>::iterator yy;
for (yy = li.begin(); yy != li.end(); yy++) {
if (*yy == y) {
break;
}
}
li.insert(yy, x);
li.erase(xx);
} else if (d == 2) {
cin >> x >> y;
list<int>::iterator xx;
for (xx = li.begin(); xx != li.end(); xx++) {
if (*xx == x) {
break;
}
}
list<int>::iterator yy;
for (yy = li.begin(); yy != li.end(); yy++) {
if (*yy == y) {
break;
}
}
li.insert(++yy, x);
li.erase(xx);
} else if (d == 3) {
cin >> x >> y;
list<int>::iterator xx;
for (xx = li.begin(); xx != li.end(); xx++) {
if (*xx == x) {
break;
}
}
list<int>::iterator yy;
for (yy = li.begin(); yy != li.end(); yy++) {
if (*yy == y) {
break;
}
}
int temp = *xx;
*xx = *yy;
*yy = temp;
} else if (d == 4) {
li.reverse();
}
}
for (auto it = li.begin(); it != li.end(); it++, it++) {
count += *it;
}
cout << count << endl;
}
}