csu 1329 一行盒子(数组模拟链表)

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

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。

Input
输入包含不超过10组数据,每组数据第一行为盒子个数n和指令条数m(1<=n,m<=100,000),以下m行每行包含一条指令。

Output
每组数据输出一行,即所有奇数位置的盒子编号之和。位置从左到右编号为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

#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 1001000
#define ll long long
using namespace std;

int nex[maxn],pre[maxn],n,m,k,tim;
int *tep,*tep2;

void init_nex_pre()
{

    for (int i=1; i<=n; i++)
        nex[i]=i+1,pre[i]=i-1;
    nex[n]=0;
}

void dele(int x)
{

    int k1=pre[x],k2=nex[x];
    nex[k1]=k2,pre[k2]=k1;
}

void inser(int k1,int mid,int k2)
{

    nex[k1]=mid,nex[mid]=k2;

    pre[k2]=mid,pre[mid]=k1;
}

void SWAP(int x,int y)
{

    int k1=pre[x],k2=nex[x],k3=pre[y],k4=nex[y];

    if (k2==y)//考虑xy相邻的情况
    {
        nex[k1]=y,nex[y]=x,nex[x]=k4;

        pre[k4]=x,pre[x]=y,pre[y]=k1;
    }
    else if (k4==x)//考虑xy相邻的情况
    {
        nex[k3]=x,nex[x]=y,nex[y]=k2;

        pre[k2]=y,pre[y]=x,pre[x]=k3;
    }
    else
    {
        nex[k1]=y,nex[y]=k2,pre[y]=k1,pre[k2]=y;
        nex[k3]=x,nex[x]=k4,pre[x]=k3,pre[k4]=x;
    }
}
int main()
{
    int cod,x,y,cas=0;
    while (cin>>n>>m)
    {
        tim=0;
        init_nex_pre();///初始
        while (m--)
        {
            cin>>cod;///输入操作
            if (cod==4)
                tim++;//这里只要记录首位交换了多少次哦
            else
            {
                cin>>x>>y; ///输入即将进行的转换
                if (cod<3 && tim&1)///如果code<3且time为奇数
                    cod=3-cod;//如果交换了奇数次,那么本来应该插在前面就相当于是现在应该插在后面,
                //T_T不好怎么表达,自己理解一下就懂了。
                if (cod==1)
                {
                    dele(x);
                    k=pre[y];
                    inser(k,x,y); ///x插在y左边
                }
                else if (cod==2)
                {
                    dele(x);
                    k=nex[y];
                     inser(y,x,k); ///x插在y右边
                }
                else if (cod==3) SWAP(x,y); ///交换
            }
        }

       if (tim&1) ///如果4交换的是奇数次
            tep=pre,tep2=nex;
        else
        tep=nex,tep2=pre;///偶数次的话
         for (int i=1; i<=n; i++)
        {
            if (tep2[i]==0)
            {
                ll ans=0;
                for (int k=1; i; i=tep[i],k++)
                    {
                        if (k&1)///转化为二进制的低位与1相与,如果为1 则为k为奇数
                           ans+=i;
                    }
                cout<<"Case "<<++cas<<": "<<ans<<endl;

                break;
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值