UVA 12657 Boxes in a Line 模拟 双向链表

        想都不用想,用list直接模拟肯定超时,只能自己手写

        用两个数组le和ri,写一个双向链表,le[x]表示盒子x左边的盒子编号,ri[x]表示盒子x右边的盒子编号,实际上就是一个双向链表 。只不过我们通过两个数组模拟之后可以O(1)的拿到某一个特定元素的左右指针而已

        另外一个变量记录这个链表的开头,输出结果的时候遍历一遍就好

        至于reverse操作,用一个bool变量标记一下,在有标记的情况下,放左边和放右边的操作需要反过来,证明的话,证明做完反操作之后有标记的这条链就是老老实实按操作做完的链表的逆置即可,想一想就知道了。

        swap的时候注意一下x和y相邻的情况,假如x和y不相邻,则需要最多要改8个指针,否则最多6个

        有点难写。。。WA了好几发,陷入 死循环了好几发。。

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;
using ll=long long;
const int maxm=100010;

int n,m,x,be,y,oper,le[maxm],ri[maxm],kcase;
bool re;
void put_left(),put_right(),swp();
ll getans();

int main(){
    ios_base::sync_with_stdio(false);
    while(cin>>n>>m){
        be=1;
        for(int i=1;i<=n;++i)
            le[i]=i-1,ri[i]=i+1;
        ri[n]=0;

        while(m--){
            cin>>oper;
            if(oper==4)
                re=!re;
            else{
                cin>>x>>y;
                if(oper==1&&!re||oper==2&&re)
                    put_left();
                else if(oper==1&&re||oper==2&&!re)
                    put_right();
                else if(oper==3)
                    swp();
            }
        }
        cout<<"Case "<<++kcase<<": "<<getans()<<endl;
        re=false;
    }
    return 0;
}

void put_left(){
    if(be==x)
        be=ri[x];
    else if(be==y)
        be=x;
    if(le[x])
        ri[le[x]]=ri[x];
    if(ri[x])
        le[ri[x]]=le[x];
    if(le[y])
        ri[le[y]]=x;
    le[x]=le[y];
    le[y]=x;
    ri[x]=y;
}

void put_right(){
    if(be==x)
        be=ri[x];

    if(le[x])
        ri[le[x]]=ri[x];
    if(ri[x])
        le[ri[x]]=le[x];
    if(ri[y])
        le[ri[y]]=x;
    ri[x]=ri[y];
    ri[y]=x;
    le[x]=y;
}

void swp(){
    if(be==x)
        be=y;
    else if(be==y)
        be=x;

    if(ri[x]==y)
        put_right();
    else if(le[x]==y)
        put_left();
    else{
        int tmp1=le[y],tmp2=ri[y];
        if(le[x])
            ri[le[x]]=y;
        if(ri[x])
            le[ri[x]]=y;
        le[y]=le[x];
        ri[y]=ri[x];
        if(tmp1)
            ri[tmp1]=x;
        if(tmp2)
            le[tmp2]=x;
        le[x]=tmp1;
        ri[x]=tmp2;
    }
}

ll getans(){
    ll ans=0;
    if(!(n&1)&&re)
        be=ri[be];
    for(bool flag=true;be;be=ri[be],flag=!flag)
    if(flag)
        ans+=be;

    return ans;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值