UVA12657 移动盒子 Boxes in a Line 题解(双向链表)

题目链接

题目思路

本质上就是模拟一下双向链表

显然操作4是要做标记的

如果现在是反转那么操作1变为操作2,操作2变为操作1

还有操作3中需要特判相邻的情况

代码

#include<cstdio>
#include<iostream>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
typedef pair<ll,int> pli;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n,m;
int l[maxn],r[maxn];
int ca;
void link(int a,int b){
    r[a]=b;
    l[b]=a;
}
void link(int a,int b,int c){
    r[a]=b;
    l[b]=a;
    r[b]=c;
    l[c]=b;
}
signed main(){
    while(scanf("%d%d",&n,&m)==2){
        for(int i=1;i<=n;i++){
            l[i]=i-1;
            r[i]=i+1;
        }
        r[n]=0;
        l[0]=1,r[0]=n;
        bool flag=1;
        for(int i=1,opt,x,y;i<=m;i++){
            scanf("%d",&opt);
            if(opt==4){
                flag=(!flag);
            }else{
                scanf("%d%d",&x,&y);
                if((opt==1||opt==2)&&(!flag)){
                    opt=3-opt;
                }
                if(opt==1){
                    //x放y左边
                    if(l[y]==x) continue;
                    link(l[x],r[x]);
                    link(l[y],x,y);
                }else if(opt==2){
                    //x放y右边
                    if(r[y]==x) continue;
                    link(l[x],r[x]);
                    link(y,x,r[y]);
                }else if(opt==3){
                    if(r[x]!=y&&l[x]!=y){
                        int lastl=l[y],lastr=r[y];
                        link(l[x],y,r[x]);
                        link(lastl,x,lastr);
                        continue;
                    }
                    if(r[y]==x) swap(x,y);
                    
                    if(r[x]==y){
                        int lastlx=l[x];
                        l[r[y]]=x;
                        r[l[x]]=y;
                        r[x]=r[y];
                        l[x]=y;
                        r[y]=x;
                        l[y]=lastlx;

                    }
                }
            }
        }
        int beg;// 起点
        for(int i=1;i<=n;i++){ //找起点
            if(flag&&l[i]==0){
                beg=i;
            }else if(!flag&&r[i]==0){
                beg=i;
            }
        }
        int cnt=1;
        ll ans=0;
        if(flag){
            while(1<=beg&&beg<=n){
                if(cnt%2==1) ans+=beg;
                beg=r[beg];
                cnt++;
            }
        }else{
             while(1<=beg&&beg<=n){
                if(cnt%2==1) ans+=beg;
                beg=l[beg];
                cnt++;
            }
        }
        printf("Case %d: %lld\n",++ca,ans);
    }
    return 0;
}

posted @ 2021-03-25 14:59  hunxuewangzi  阅读(45)  评论(0编辑  收藏  举报