紫书题目移动盒子

题目的意思是,你有一行的盒子,這邪恶盒子是按照序号1-n的顺序进行排列的,现在你要做的就是,在给你一个n和一个m的时候,其中的n是指由多少个盒子在排列,m是指要执行多少次的操作,这里一共有4中操作,其中一是,输入1 1 2就是执行第一次操作,如果1实在2的左边这不用进行操作,如果1在2的右边那么就要把1放到2的左边,同样的2号的操作就是输入2 2 3,意思是进行2操作,如果2在3 的右边就不用进行操作,如果2在3的左边就要把2移动到3的右边,还有就是3号操作,直接将输入的两个数进行互相交换。至于4操作就是将这一列的数字首位倒置。

 
变动一个数子的话只会涉及到整个数字左右的两个数字,所以的话就要两个标记来进行变动。这里设置了两个数组来表示这两个标记。4种操作中的第四个可以不用进行任何的动作,只需要进行一次标记就可以完成第四个操作了,所以这里可以设置一个标记,每次进行操作的时候通过判断这个标记是否存在来进行操作,比如如果这个标记是存在的,那么进行第一个操作的时候就变成了进行第二个操作了,而第三个操作就可以不用进行了。同时书上的源程序有很多值得学习的地方,例如在输入标记的数组right的时候,使用的是right[i]=(i+1)%(n+1);这样的好处就是可以防止数据的输入越界。还有就是在写程序的时候要注意的是每一部分要规范的进行书写,让人感觉层次分明。还有很巧妙的一点就是在最后的时候当标记标记显示是执行过4号操作的时候,要计算相反的序号地和,书中是通过计算前n项的和减去计算出来的奇数项。
源代码:
#include<cstdio>
#include<cstring>
const int maxn=100000+10;
int n,left[maxn],right[maxn];
void link(int L,int R)
{
    right[L]=R;
    left[R]=L;
}
void swap(int &x,int &y)
{
    int a;
    a=x;
    x=y;
    y=a;
}
int main()
{
    int m,kase=0;
    while(scanf("%d%d",&n,&m)==2)
    {
        for(int i=1;i<=n;i++)
        {
            left[i]=i-1;
            right[i]=(i+1)%(n+1);
        }
        right[0]=1;
        left[0]=n;
 
        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;
                if(op==1&&X==left[Y])continue;
                if(op==2&&Y==right[X])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(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);
                    }
                }
            }
        }
 
        int b=0;
        long long ans=0;
        for(int i=1;i<=n;i++)
        {
            b=right[b];
            if(i%2==1)
                ans+=b;
        }
        if(inv&&n%2==0)
            ans=(long long)n*(n+1)/2-ans;
        printf("Case %d: %lld\n",++kase,ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/yewa/p/7243534.html