Uva 12657 Boxes in a Line 链表 模拟

题目

题目链接: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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值