【数组模拟链表(双向)】UVA - 12657 Boxes in a Line

Problem Description

给你n和m,分别对应1-n的编号,和m行操作,有四种情况1 X Y:X移动到Y的左边, 2 X Y: X移动到Y的右边, 3 X Y:交换位置, 4 反转整个编号。

代码:

#include<bits/stdc++.h>
using namespace std;
int lt[100055];//记录i点的左边下标
int rt[100055];//记录i点的右边下标
void link(int L, int R)//连接L,R,L在左边R在右边的连接方式
{
    rt[L] = R;
    lt[R] = L;
}
int main()
{
    int n, m, cas = 1;
    while(~scanf("%d %d", &n, &m))
    {
        for(int i = 1; i <= n; i++)//初始化记录
        {
            rt[i] = (i + 1) % (n + 1);
            lt[i] = i - 1;
        }
        rt[0] = 1; lt[0] = n;


        int op, x, y, inv = 0;
        while(m--)
        {
            scanf("%d", &op);
            if(op == 4) inv = !inv;//标记反转
            else
            {
                scanf("%d %d", &x, &y);
                if(op != 3 && inv) op = 3 - op; //如果反转 1 变为2, 2 变为1
                if(op == 1 && x == lt[y]) continue;
                if(op == 2 && x == rt[y]) continue;

                int Lx = lt[x], Rx = rt[x], Ly = lt[y], Ry = rt[y];
                if(op == 1)//xy的左边
                {
                    link(Lx, Rx); link(Ly, x); link(x, y);
                }
                else if(op == 2)//xy的右边
                {
                    link(Lx, Rx); link(x, Ry); link(y, x);
                }
                else if(op == 3)//交换位置
                {
                    if(rt[y] == x)//相邻
                    {
                        link(Ly, x); link(x, y); link(y, Rx);
                    }
                    else if(rt[x] == y)//相邻
                    {
                        link(Lx, y); link(y, x); link(x, Ry);
                    }
                    else//不相邻
                    {
                        link(Lx, y); link(y, Rx); link(Ly, x); link(x, Ry);
                    }
                }
            }

        }
        int b = 0;
        long long ans = 0;
        for(int i = 1; i <= n; i++)
        {
            b = rt[b];
            if(i % 2 != 0) ans += b;
        }
        if(inv && n % 2 == 0) ans = (long long) n * (n + 1) / 2 - ans;//n为奇数求和结果不变
        printf("Case %d: %lld\n", cas++, ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值