题目
题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=110383#problem/B
题目来源:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=110383#overview
简要题意:实现四种操作,两种移动,交换和反转。
题解
这题可以使用链表来解决,由于涉及到交换和反转,所以还是比较复杂的。
可以维护一个反转的变量,然后只在原本顺序的链表中维护位置。
于是反转情况下插入左边变为插入右边,插入右边变成插入左边,交换则是不变的。
交换的时候如果交换的节点相邻,则很可能会产生一些错误,得小心。
处理的方式一种是进行特判,特殊处理,这样会长一些,交换的代码(代码1)。
再多保存一些数据就能缩短代码,保存某编号在哪个节点,每个节点保存其中的编号(代码2)。
主要的想法在代码中体现、
代码1
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
// head
const int N = 1e5+5;
struct Node {
int l, r;
Node(int l, int r) : l(l), r(r) {}
Node() {}
};
struct List {
int n;
Node a[N];
bool st;
void init(int n) {
this->n = n;
for (int i = 0; i <= n+1; i++) {
a[i] = Node(i-1, i+1);
}
st = false;
}
void reverseState() {
st = !st;
}
void handleInsert(int x, int y, bool left) {
if (st ^ left) {
insertLeft(x, y);
} else {
insertRight(x, y);
}
}
void insertLeft(int x, int y) {
removeNode(x);
insertNode(x, a[y].l, y);
}
void insertRight(int x, int y) {
removeNode(x);
insertNode(x, y, a[y].r);
}
void swapNode(int x, int y) {
int xl = a[x].l, xr = a[x].r;
int yl = a[y].l, yr = a[y].r;
if (a[x].r == y) {
a[xl].r = y;
a[yr].l = x;
a[x] = Node(y, yr);
a[y] = Node(xl, x);
} else if (a[x].l == y) {
swapNode(y, x);
} else {
removeNode(x);
removeNode(y);
insertNode(x, yl, yr);
insertNode(y, xl, xr);
}
}
void removeNode(int x) {
int l = a[x].l, r = a[x].r;
a[l].r = r;
a[r].l = l;
}
void insertNode(int x, int l, int r) {
a[x] = Node(l, r);
a[l].r = a[r].l = x;
}
LL getAns() {
LL ans = 0;
if (n & 1) st = false;
int cur = 0;
for (int i = 1; i <= n; i++) {
if ((i & 1) ^ st) {
ans += a[cur].r;
}
cur = a[cur].r;
}
return ans;
}
};
List list;
int main() {
int n, m, op, x, y, cas = 1;
while (scanf("%d%d", &n, &m) == 2) {
list.init(n);
for (int i = 0; i < m; i++) {
scanf("%d", &op);
if (op == 4) {
list.reverseState();
} else {
scanf("%d%d", &x, &y);
if (op == 1) {
list.handleInsert(x, y, true);
} else if (op == 2) {
list.handleInsert(x, y, false);
} else {
list.swapNode(x, y);
}
}
}
printf("Case %d: %lld\n", cas++, list.getAns());
}
return 0;
}
代码2
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
// head
const int N = 1e5+5;
struct Node {
int l, r, no;
Node(int l, int r, int no) : l(l), r(r), no(no) {}
Node() {}
};
struct List {
int n;
Node a[N];
int no[N];
bool st;
void init(int n) {
this->n = n;
st = false;
for (int i = 0; i <= n+1; i++) {
a[i] = Node(i-1, i+1, i);
no[i] = i;
}
}
void reverseState() {
st = !st;
}
void handleInsert(int x, int y, bool left) {
x = no[x], y = no[y];
if (st ^ left) {
insertLeft(x, y);
} else {
insertRight(x, y);
}
}
void insertLeft(int x, int y) {
removeNode(x);
insertNode(x, a[y].l, y);
}
void insertRight(int x, int y) {
removeNode(x);
insertNode(x, y, a[y].r);
}
void swapNode(int x, int y) {
swap(no[x], no[y]);
swap(a[no[x]].no, a[no[y]].no);
}
void removeNode(int x) {
int l = a[x].l, r = a[x].r;
a[l].r = r;
a[r].l = l;
}
void insertNode(int x, int l, int r) {
a[x] = Node(l, r, a[x].no);
a[l].r = a[r].l = x;
}
LL getAns() {
if (n & 1) st = false;
LL ans = 0;
int cur = a[0].r;
for (int i = 1; i <= n; i++) {
if ((i & 1) ^ st) {
ans += a[cur].no;
}
cur = a[cur].r;
}
return ans;
}
};
List list;
int main() {
int n, m, op, x, y, cas = 1;
while (scanf("%d%d", &n, &m) == 2) {
list.init(n);
for (int i = 0; i < m; i++) {
scanf("%d", &op);
if (op == 4) {
list.reverseState();
} else {
scanf("%d%d", &x, &y);
if (op == 1) {
list.handleInsert(x, y, true);
} else if (op == 2) {
list.handleInsert(x, y, false);
} else {
list.swapNode(x, y);
}
}
}
printf("Case %d: %lld\n", cas++, list.getAns());
}
return 0;
}