UVa 12657-Boxes in a Line 双向链表

题目链接:https://cn.vjudge.net/problem/UVA-12657

Boxes in a Line

You have n boxes in a line on the table numbered 1…n from left to right. Your task is to simulate 4 kinds of commands:

  • 1 X Y : move box X to the left to Y (ignore this if X is already the left of Y)
  • 2 X Y : move box X to the right to Y (ignore this if X is already the right of Y)
  • 3 X Y : swap box X and Y
  • 4 : reverse the whole line.

Commands are guaranteed to be valid, i.e. X will be not equal to Y.

For example, if n = 6, after executing 1 1 4, the line becomes 2 3 1 4 5 6. Then after executing 2 3 5, the line becomes 2 1 4 5 3 6. Then after executing 3 1 6, the line becomes 2 6 4 5 3 1. Then after executing 4, then line becomes 1 3 5 4 6 2

Input

There will be at most 10 test cases. Each test case begins with a line containing 2 integers n,m(1≤n,m≤100,000). Each of the following m lines contain a command.

Output

For each test case, print the sum of numbers at odd-indexed positions. Positions are numbered 1 to n from left to right.

Sample Input

6 4 
1 1 4 
2 3 5 
3 1 6 

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

题意:你有一行盒子从左至右编号依次为1,2,3,4……,n。可以执行以下四种指令:

  • 1 X Y 表示把盒子X移动到Y左边(如果X已经在Y的左边则忽略此指令)。
  • 2 X Y 表示把盒子X移动到Y右边(如果X已经在Y的右边则忽略此指令)。
  • 3 X Y 表示交换盒子X Y 的位置。
  • 4 表示反转整条链。

执行完所有指令后输出奇数位上数字之和。

思路:用双向链表来记录每一个数字的左边和右边,从0开始,0的右边为编号为1的数,0的右边为编号为n的数。其中利用link函数来连接两个节点,并且,对于指令4,可以巧妙的采用标记的方法,而不是真的将整个链反转。若标记为真,则遇到指令1,2时,可用op=3-op 来转化。当遇到指令3时,还需考虑X Y 相邻的情况。

void link(int l,int r)
{
    rightt[l]=r;
    leftt[r]=l;
}

参考代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
using namespace std;
const int maxn=100005;
int rightt[maxn],leftt[maxn];
void link(int l,int r)
{
    rightt[l]=r;
    leftt[r]=l;
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n,m,kase=0;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1; i<=n; i++) //初始化left和right数组
        {
            leftt[i]=i-1;
            rightt[i]=(i+1)%(n+1);//r[n]=0;
        }
        rightt[0]=1;
        leftt[0]=n;
        int inv=0,x,y,op;
        while(m--)
        {
            scanf("%d",&op);
            if(op==4)
                inv=!inv;
            else
            {
                scanf("%d%d",&x,&y);
                if(op==3&&leftt[x]==y)
                {
                    int t=x;
                    x=y;
                    y=t;
                }
                if(op!=3&&inv)
                    op=3-op;
                if(op==1&&x==leftt[y])
                    continue;
                if(op==2&&x==rightt[y])
                    continue;
               //此处另设变量来存储原始的ly,lx,ry,rx值。
                int ly=leftt[y],lx=leftt[x],rx=rightt[x],ry=rightt[y];
                if(op==1)
                {
                    link(lx,rx);
                    link(ly,x);
                    link(x,y);
                }
                else if(op==2)
                {
                    link(lx,rx);
                    link(y,x);
                    link(x,ry);
                }
                else if(op==3)
                    if(leftt[y]==x)
                    {
                        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 summ=0;
        for(int i=1;i<=n;i++)
        {
            b=rightt[b];
            if(i%2==1)
                summ+=b;
        }
        if(inv&&n%2==0)
            summ=(long long)n*(n+1)/2-summ;
        printf("Case %d: %lld\n",++kase,summ);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值