【UVA 12657】Boxes in a Line 题解(静态双向链表)

您在编号为1的表格上有n个方框。n从左到右。您的任务是模拟4
命令类型:
•1 X Y:将框X向左移动到Y(如果X已经是Y的左侧,则忽略此项)
•2 X Y:将框X向右移动到Y(如果X已经是Y的右侧,则忽略此项)
•3 X Y:交换盒X和Y
•4:反转整条线路。
命令保证有效,即X不等于Y。
例如,如果n=6,在执行1 1 4之后,该行变为2 3 1 4 5 6。然后在执行之后
2 3 5,直线变为2 1 4 5 3 6。然后在执行3 1 6之后,该行变为2 6 4 5 3 1。
然后在执行4之后,行变为1 3 5 4 6 2

输入
最多有10个测试用例。每个测试用例以包含2个整数n,m的行开始
(1≤n,m≤100000)。以下m行中的每一行都包含一个命令。
输出
对于每个测试用例,在奇数索引位置打印数字的和。位置编号为1到n
从左到右。

Sample Input
6 4
1 1 4
2 3 5
3 1 6
4
6 3
1 1 4
2 3 5
3 1 6
100000 1
4
Sample Output
Case 1: 12
Case 2: 9
Case 3: 2500050000

思路

实现静态双向链表及插入元素、删除元素、移动元素、交换元素等操作。交换元素a和b时有三种情况,ab相邻且a在b前、ab相邻且a在b后、ab不相邻,要分情况解决。用rev来标记链表是否被翻转,若被翻转输出反向奇数索引之和,反向奇数索引之和等于所有索引之和减去正向奇数索引之和。

AC代码


#include <iostream>
#include <list>
#include <algorithm>
#define AUTHOR "HEX9CF"
using namespace std;

#define maxn 100005

int n, m;
int rev = 1;
int cmd;
int l[maxn], r[maxn];
int x, y;
int k = 1;

void link(int a, int b)
{
    r[a] = b;
    l[b] = a;
}

void del(int x)
{
    link(l[x], r[x]);
}

void ins(int a, int c, int b)
{
    link(a, c);
    link(c, b);
}

void swp(int x, int y)
{
    if (l[y] == x)
    {
        int a = l[x];
        int b = r[y];
        link(a, y);
        link(y, x);
        link(x, b);
    }
    else if (r[y] == x)
    {
        int a = l[y];
        int b = r[x];
        link(a, x);
        link(x, y);
        link(y, b);
    }
    else
    {
        int a = l[x];
        int b = r[x];
        int c = l[y];
        int d = r[y];
        link(c, x);
        link(x, d);
        link(a, y);
        link(y, b);
    }
}

void print()
{
    cout << "l ";
    for (int i = 1; i <= n; i++)
    {
        cout << l[i] << " ";
    }
    cout << endl
         << "r ";
    for (int i = 1; i <= n; i++)
    {
        cout << r[i] << " ";
    }
    cout << endl;
}

void show()
{
    int t = 0;
    for (int i = 1; i <= n; i++)
    {
        t = r[t];
        cout << t << " ";
    }
    cout << endl;
}

int main()
{
    while (cin >> n >> m)
    {
        rev = 1;
        for (int i = 1; i <= n + 1; i++)
        {
            l[i] = i - 1;
            r[i] = (i + 1) % (n + 1);
        }
        l[0] = n;
        r[0] = 1;
        // show();

        for (int i = 0; i < m; i++)
        {
            cin >> cmd;
            if (4 == cmd)
            {
                rev *= -1;
                continue;
            }
            cin >> x >> y;
            if ((1 == cmd && rev > 0) || (2 == cmd && rev < 0))
            {
                // 将盒子x 移动到y 的左侧
                // cout << "1 " << rev << endl;
                del(x);
                ins(l[y], x, y);
            }
            else if ((2 == cmd && rev > 0) || (1 == cmd && rev < 0))
            {
                // 将盒子x 移动到y 的右侧
                // cout << "2 " << rev << endl;
                del(x);
                ins(y, x, r[y]);
            }
            else if (3 == cmd)
            {
                // 交换盒子x 和y 的位置。
                // cout << x << " swap " << y << endl;
                swp(x, y);
            }
            // show();
        }
        // print();
        // show();
        int t = 0;
        long long sum = 0, j = 0;
        for (int i = 1; i <= n; i++)
        {
            t = r[t];
            sum += t;
            if (i % 2)
            {
                j += t;
            }
        }
        // cout << sum << endl;
        if (!(n % 2) && (rev < 0))
        {
            j = sum - j;
        }
        cout << "Case " << k << ": " << j << endl;
        k++;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值