ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Box in line 链表不是直白的可变数组

2021-09-13 21:00:45  阅读:165  来源: 互联网

标签:Box right int void 链表 pNode link && line


uva 12657

  • 最开始在rverse = !rverser这里出现了问题,写成了rverse = ~rverse,这样写rverse的值是不发生变化的

  • 整体思路很清晰,自己做链表。一开始就知道不能反转,做了标记rverse,但是查找直接用O(N),必然超时。

  • 最开始也试着想了下存储位置,但是没想透——以为每次变化都会波及前边的。实际上存储每一个的指针,是很方便的。所以有优化的思路还是要想清晰一些

  • 做法太过麻烦耗资源,不断申请/销毁内存,函数调用等都会增加负担

  • 书上的亮点需要学习

    1. 统一化。如处理反转操作,因为只有op == 1 || op == 2操作受影响,所以只需考虑3 - op即可.再如交换位置时,对X,Y相邻情况的特判,有YXXY两种情况,只需swap一下即可。
    2. 游标法(听说是叫这个?)还是链表的思想,只需链表思想。
      开两个数组leftright,第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;
}

标签:Box,right,int,void,链表,pNode,link,&&,line
来源: https://blog.csdn.net/qq_51279492/article/details/120275281

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有