Boxes in a Line UVA - 12657 (双向链表)

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

题目大意:输入n,m  代表有n个盒子 每个盒子最开始按1~n排成一行  m个操作,

1 x y  :把盒子x放到y的左边

2 x y: 把盒子x放到y 的右边

3 x y:调换x y盒子的位置

4    表示反转整条链

思路:也是很明显的暴力 模拟 。  但是值得提的是 虽然是暴力,但是却是用的双向链表来暴力。  

有很多要注意的地方 :

当操作4的时候,我们可以把本次操作记录一下,不必直接把全部的位置反转 试想一下,如果每次出现一个4  每次都反转  那多麻烦 (我们要反转的话,首先得找到最后一个盒子,然后从最后一个盒子往前重新存储一遍)

但是如果有记录操作4注意再碰到其他操作 也要随之改变  :

当有记录4的时候  操作1就相当于操作2     操作2相当于操作1  

还有注意的是  操作3  两个盒子交换位置   :  两个盒子相邻和不相邻是不一样的  切记!!!

最后   要输出结果的话 :  注意有没有操作4  如果有操作4的话  如果是奇数 反转一次对结果没有影响   但是偶数 的话    反转一次 我们现在求的刚好的偶数位的   总的减掉就是答案了

具体看代码:

#include<iostream>
#include<string.h>
#include<vector>
#include<stdio.h>
using namespace std;
const int maxn=1e5+5;
int n;
int Left[maxn];
int Right[maxn];
void link(int l,int r) //两个节点相连
{
    Right[l]=r;
    Left[r]=l;
}
int main()
{
    int m,ca=0;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)//存好节点
        {
            Left[i]=i-1;
            Right[i]=(i+1)%(n+1);//这里为何%(n+1)   试想一下 最后一个元素的右端是谁   显然是第一个元素0
        }
        Left[0]=n;
        Right[0]=1;
        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&&Right[y]==x) swap(x,y);//
                if(op!=3&&inv) op=3-op;//当调整一次顺序的时候 操作1和2  刚好相反 可以自己举例子
                if(op==1&&x==Left[y]) continue;//已经满足条件了
                if(op==2&&x==Right[y]) continue;
                int lx=Left[x],rx=Right[x],ly=Left[y],ry=Right[y];
                if(op==1) //调整位置
                {
                    link(lx,rx);
                    link(ly,x);
                    link(x,y);
                }
                else if(op==2)
                {
                    link(lx,rx);
                    link(x,ry);
                    link(y,x);
                }
                else if(op==3)//注意两者相连和不相连交换位置操作是不一样的  !!!
                {
                    if(Right[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=Right[b];//其实b就是i位置对应的值  可以仔细想一下
            if(i%2==1) ans+=b;
        }
        if(inv&&n%2==0) ans=(long long)n*(n+1)/2-ans;//自己举个例子就可以明白 n为奇数没有影响
        printf("Case %d: %lld\n",++ca,ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/caijiaming/p/10345830.html