UVa 12657 - Boxes in a Line ( 双向链表 )

题意

你有一行盒子,从左到右依次编号为1, 2, 3,…, n。可以执行以下4种指令:
1 X Y表示把盒子X移动到盒子Y左边(如果X已经在Y的左边则忽略此指令)。
2 X Y表示把盒子X移动到盒子Y右边(如果X已经在Y的右边则忽略此指令)。
3 X Y表示交换盒子X和Y的位置。
4 表示反转整条链。

思路

双向链表
每次操作只需修改链表中的元素指向
另外, 如果程序一直在反转整条链, 如果一直操作的话必然复杂度很高
因为题目只求所有奇数位置标号之和, 当boxnum为奇数, 盒子逆序无影响
boxnum为偶数时才有影响, 再具体判断即可 . 所以将反转链操作用bool标记即可

AC代码

#include <iostream>
#include <cstdio>
#include <cstring>


using namespace std;
typedef long long ULL;
const int maxn = 100000 + 10;
int l[maxn],r[maxn];

void link( int left, int right ){
    r[left] = right;
    l[right] = left;
}

int main()
{
    int boxnum, casenum, i;
    int x, a, b, num = 0;
    ULL result;
    bool ok;
    while( ~scanf("%d%d",&boxnum, &casenum) ){
        for( i = 1; i <= boxnum; i++ ){
            l[i] = i - 1;
            r[i] = ( i + 1 )  % ( boxnum + 1 );
        }
        l[0] = boxnum;
        r[0] = 1;
        ok = false;
        while( casenum-- ){
            scanf("%d",&x);
            if( x == 4 ){   //反转
                ok = !ok;
                continue;
            }
            scanf("%d%d",&a,&b);
            if( x == 3 && r[b] == a )   swap(a,b);
            if( x != 3 && ok )  x = 3 - x;
            if( (x == 1 && l[b] == a) || (x == 2 && r[b] == a) )    continue;
            int la = l[a], ra = r[a], lb = l[b], rb = r[b];
            if( x == 1 ){
                link(la, ra);
                link(a, b);
                link(lb, a);
            }
            else if( x == 2 ){
                link(la, ra);
                link(b, a);
                link(a, rb);
            }
            else if( x == 3 ){
                if( ra == b ){
                    link(la, b);
                    link(b, a);
                    link(a, rb);
                }
                else{
                    link(la, b);
                    link(b, ra);
                    link(lb, a);
                    link(a, rb);
                }
            }
        }
        int t = 0;
        result = 0;
        for( int i = 1; i <= boxnum; i++ ){
            t = r[t];
            if( i % 2 != 0 )    result += t;
        }
        if( ok && boxnum % 2 == 0 )
            result = (ULL)boxnum*(boxnum+1)/2 - result;
        //cout << boxnum*(boxnum+1)/2 ;
        printf("Case %d: %llu\n",++num, result);
    }
    return 0;
}
posted @ 2018-02-09 21:38  JinxiSui  阅读(125)  评论(0编辑  收藏  举报