例题6-5 UVA 12657 Boxes in a Line 移动盒子

来源:互联网 发布:菜鸟网络总部 编辑:程序博客网 时间:2024/06/13 07:37

感觉很好的一道题目。

看了很久:用到了双向链表。

1。用了两个数组left[maxn],right[maxn]代表当前元素的左边一个或者右边一个,当这个值为0的时候代表不存在!

2。对于4号命令,逆转整个序列,并没有真正的逆转,而是用inv 记录 是否逆转,利用了逆转两次等于没有逆转这个道理。逆转只会影响到1命令和2命令,3命令是XY换一下,并不会影响到,所以对与1和2,直接op = 3 - op即可!利用inv这个变量也有利于最后的输出,最后输出发现inv是0的话,就是没逆转,那么直接把奇数位置的数加起来即可,反之,要用总和减去这个偶数序列,(因为当n是偶数并且逆转的情况,sum其实是偶数位置!)

3。最后注意的一点,对于3号命令,是XY置换,XY相邻和XY相隔很多元素,处理是不一样的。


代码如下:


#include<iostream>#include<cstdio>const int maxn = 100000 + 10;typedef long long ll;int right[maxn],left[maxn];void link(int x,int y){    right[x]=y; left[y]=x;}int main(){    int n,m,cnt=0;    while(scanf("%d%d",&n,&m) == 2){        for (int i = 0; i <= n; ++i){            left[i]=i-1;            right[i]=(i+1)%(n+1);        }        left[0]=n; right[n]=0;        int op,inv=0,X,Y;        while(m--){            scanf("%d",&op);            if (op == 4)inv = !inv;            else{                scanf("%d%d",&X,&Y);                if (inv && op != 3)op = 3 - op;                if (op == 1 && right[X] == Y)continue;                if (op == 2 && right[Y] == X)continue;                int LX=left[X],RX=right[X],RY=right[Y],LY=left[Y];                if (op == 1){link(LX,RX);link(LY,X);link(X,Y);}                if (op == 2){link(LX,RX);link(Y,X);link(X,RY);}                if (op == 3){                    if (right[X] == Y){link(LX,Y);link(Y,X);link(X,RY);}                    else if (right[Y] == X){link(LY,X);link(X,Y);link(Y,RX);}                    else {link(LX,Y);link(Y,RX);link(LY,X);link(X,RY);}                }            }        }        ll ans=0;        int b = 0;        for (int i = 1; i <= n; ++i){            b = right[b];            if (i % 2 == 1)ans+=b;        }        if (n % 2 == 0 && inv)ans = (ll)(n+1)*n/2-ans;        printf("Case %d: %lld\n",++cnt,ans);    }    return 0;}


0 0