-
最开始在
rverse = !rverser
这里出现了问题,写成了rverse = ~rverse
,这样写rverse
的值是不发生变化的 -
整体思路很清晰,自己做链表。一开始就知道不能反转,做了标记
rverse
,但是查找直接用O(N),必然超时。 -
最开始也试着想了下存储位置,但是没想透——以为每次变化都会波及前边的。实际上存储每一个的指针,是很方便的。所以有优化的思路还是要想清晰一些
-
做法太过麻烦耗资源,不断申请/销毁内存,函数调用等都会增加负担
-
书上的亮点需要学习
- 统一化。如处理反转操作,因为只有
op == 1 || op == 2
操作受影响,所以只需考虑3 - op
即可.再如交换位置时,对X,Y相邻情况的特判,有YX
和XY
两种情况,只需swap
一下即可。 - 游标法(听说是叫这个?)还是链表的思想,只需链表思想。
开两个数组left
和right
,第i个值分别表示编号为i的盒子左右两边的盒子编号。
再写一个函数Link(int L, int R)
,表示将链接编号为L、R的盒子
这样就省去了new, delete, insert
等操作,简化了逻辑
- 统一化。如处理反转操作,因为只有
-
再回想一下,截至目前,书上对于链表的应用,实际上是只存储单一节点的某端的索引,像这道题,盒子编号是连续且固定的;上一题,字符串中的字符位置是固定的;如果需要连续索引但题中不连续也可以用
map
做映射,总之这种方法具有通用性,也体现了很灵活的编程思想
书上代码
#include <cstdio>
int right[100010];
int left[100010];
void link(int L, int R) {
right[L] = R;
left[R] = L;
}
void swap(int* x, int* y) {
int t = *x;
*x = *y;
*y = t;
}
int main() {
int m, n, kase = 0;
while (scanf("%d%d", &m, &n)==2) {
for (int i = 1; i <= m; ++i) {
left[i] = i - 1;
right[i] = (i + 1) % (m + 1);
}
left[0] = m; right[0] = 1;
int inv = 0;
while (n--) {
int a, b, c;
scanf("%d", &a);
if (a == 4) { inv = !inv; continue; }
else scanf("%d%d", &b, &c);
if (inv && a != 3) a = 3 - a;
if (a == 3 && right[c] == b) swap(&b, &c);
if (a == 1 && right[b] == c) continue; else if(a == 1 && left[b] == c) { a = 3; swap(&b, &c); }
if (a == 2 && left[b] == c) continue; else if (a == 2 && right[b] == c)a = 3;
int Lb = left[b], Rb = right[b], Lc = left[c], Rc = right[c];
if (a == 1) { link(Lb, Rb); link(Lc, b); link(b, c); }
if (a == 2) { link(Lb, Rb); link(b, Rc); link(c, b); }
if (a == 3 && right[b] == c) {link(Lb, c); link(c, b); link(b, Rc); }
else if (a == 3) { link(Lb, c); link(c, Rb); link(Lc, b); link(b, Rc); }
}
long long ans = 0;
for (int i = right[0]; (i && !(m&1)) || (left[i] && (m&1) && ans) || !ans; i = right[right[i]]) {
ans += i;
}
if (inv)ans = (long long)m * (m + 1) / 2 - ans;
printf("Case %d: %lld\n",++kase, ans);
}
return 0;
}
自己写的不太好的
#include <iostream>
#include <fstream>
#define TEST 1
using namespace std;
struct Line;
class Node;
typedef Node *pNode;
class Node
{
friend struct Line;
public:
Node(int _k = 0, pNode a = NULL, pNode b = NULL)
: k(_k), l(a), r(b) {}
private:
int k;
pNode l, r;
};
struct Line
{
public:
Line(int _n = 0) : n(_n), rverse(false) { init(); }
~Line();
void debug(ostream &os)
{
static int cnt = 0;
os << "##" << ++cnt << ": ";
for (pNode p = head->r; p; p = p->r)
os << p->k << (p->r == NULL ? "\n" : "->");
}
void putx2y(int mode);
void x_y();
void Reverse() { rverse = !rverse; }
long long oddSum();
private:
pNode head;
bool rverse;
int n;
pNode *pos;
pair<int, int> find_xy(pNode &, pNode &);
pair<int, int> find_xy2(pNode &, pNode &);
void init();
void del(pNode);
void push_back(pNode, int);
};
int main()
{
ofstream ofs;
if (TEST)
{
ofs.open("/home/lixiaoqi/Documents/Code/C++/1.txt");
if (!ofs.is_open())
throw runtime_error("FILE NOT OPEN!");
}
ostream &os = TEST ? ofs : cout;
int n, k, cnt = 0;
while (cin >> n)
{
Line L(n);
cin >> n;
while (n--)
{
cin >> k;
if (k == 1 || k == 2)
L.putx2y(k);
else if (k == 3)
L.x_y();
else if (k == 4)
L.Reverse();
else
throw runtime_error("ERROR_INPUT");
if (TEST)
L.debug(cout);
}
os << "Case " << ++cnt << ": " << L.oddSum() << '\n';
}
return 0;
}
long long Line::oddSum()
{
long long ret = 0LL;
pNode p = head->r;
if (n % 2 == 0 && rverse && p)
p = p->r;
while (p)
{
ret += p->k;
p = p->r;
if (p)
p = p->r;
}
return ret;
}
void Line::x_y()
{
int x, y;
cin >> x >> y;
pNode X = pos[x];
pNode Y = pos[y];
push_back(X, y);
push_back(Y, x);
del(X);
del(Y);
}
void Line::putx2y(int mode)
{
int x, y;
cin >> x >> y;
pNode X = pos[x], Y = pos[y];
push_back((mode == 1 && !rverse || mode == 2 && rverse) ? Y->l : Y, x);
del(X);
}
void Line::push_back(pNode p, int k)
{
pNode R = p->r;
p->r = new Node(k, p, R);
pos[k] = p->r;
if (R)
R->l = p->r;
}
void Line::del(pNode d)
{
d->l->r = d->r;
if (d->r)
d->r->l = d->l;
delete d;
}
void Line::init()
{
head = new Node;
pos = new pNode[n + 1];
if (!head || !pos)
throw runtime_error("ERROR_INIT!");
pNode curr = head;
for (int i = 1; i <= n; ++i)
{
curr->r = new Node(i, curr, NULL);
curr = curr->r;
pos[i] = curr;
}
}
Line::~Line()
{
pNode d;
while (head)
{
d = head;
head = head->r;
delete d;
}
delete[] pos;
}