UVA - 12657 Boxes in a Line【数组模拟双向链表】C++

题目:https://odzkskevi.qnssl.com/174f024bd53291a2e247beeba3bb72fe?v=1531723110

思路:这题是按照紫书上的思路来做的。就一边贴代码一边讲解吧。其实按照紫书上代码来的话,在草稿纸上画一遍就明白了。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int Right[100005],Left[100005];//Right[i]代表i左边的结点的编号,left[i]代表i右边的结点的编号
void link(int L,int R)//连接两个结点,注意:这个函数只是把两个结点中间相连了,也就是两个点中间不再有别的点了,但是他们另一边的值还要做处理
{
    Right[L]=R;
    Left[R]=L;
}
int main()
{
    int n,num;
    int tot=0;
    while(scanf("%d%d",&n,&num)!=EOF){
        tot++;
        memset(Right,0,sizeof(Right));
        memset(Left,0,sizeof(Left));
        for(int i=1;i<=n;i++)
        {
            Left[i]=i-1;
            Right[i]=(i+1)%(n+1);
        }
        Left[0]=n,Right[0]=1;
        int inv=0;int op;int x,y;
        while(num--)
        {
            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;
                if(op==1&&Left[y]==x)continue;
                if(op==2&&Right[y]==x)continue;

                int lx=Left[x],rx=Right[x],ly=Left[y],ry=Right[y];
                if(op==1){//拿op=1来举例,先让lx和rx相连,于是x被完美地挤出去了,但是x的两边的值依然是lx和rx,所以我们要改变x两边的值,先让x的左边等于ly,ly的右边等于x,即ly和x相连,再改变x的右边,让x和y相连。
                    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(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);
                    }
                }
            }
        }
        long long int sum=0;
        int b=0;
        for(int i=1;i<=n;i++)
        {
            b=Right[b];
            if(i%2==1)sum=sum+b;
        }
        if(inv&&n%2==0)sum=(long long int)(1+n)*n/2-sum;//当n是偶数且inv是1时(也就是链表反向的时候,我们求的和是偶数的和而不是奇数的和,所以要用总数减一下)
        printf("Case %d: %lld\n",tot,sum);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zero_979/article/details/81155208
今日推荐