uva 12657 Boxes in a Line

来源:互联网 发布:淘宝well运动正吗 编辑:程序博客网 时间:2024/06/03 09:47

题目:Boxes in a Line


题意:

有n个盒子,初始按1~n排列。

给定4个操作:

 1 x y  将x移动到y的左边;

 2 x y  将x移动到y的右边;

 3 x y  将x和y的位置交换;

 4        将序列的位置颠倒。

输出变换后在奇数位置的木块编号总和。


思路:

用链表存储木块的位置。由于操作4比较费时间,所以可以用 bool rev 来表示序列是否颠倒了,true为颠倒。每次执行操作4时,rev^=1。当rev=true时,操作1和2是反着的。


注意:

1、最后结果用 long long 存储。

2、操作3要讨论两木块是否挨着。


代码:

#include<cstdio>#include<iostream>#include<string>#include<cstring>#include<vector>#include<set>#include<map>#include<algorithm>#include<cmath>#include<queue>#include<stack>#include<deque>using namespace std;struct list {int front,back;list(int one,int two) {front=one,back=two;}list() {}};int n,m;list a[100005];void init() {for(int i=1; i<=n; i++) {a[i]=list(i-1,i+1);}a[1].front=100001;a[n].back=100001;}int main() {int T=0;while(scanf("%d%d",&n,&m)==2) {init();bool rev=0;while(m--) {int opr;scanf("%d",&opr);if((opr==1&&rev==0)||(opr==2&&rev==1)) {int x,y;scanf("%d%d",&x,&y);a[a[x].back].front=a[x].front;a[a[x].front].back=a[x].back;a[a[y].front].back=x;a[x].back=y;a[x].front=a[y].front;a[y].front=x;}if((opr==2&&rev==0)||(opr==1&&rev==1)) {int x,y;scanf("%d%d",&x,&y);a[a[x].back].front=a[x].front;a[a[x].front].back=a[x].back;a[a[y].back].front=x;a[x].front=y;a[x].back=a[y].back;a[y].back=x;}if(opr==3) {int x,y;scanf("%d%d",&x,&y);if(a[x].front==y) {int s=x;x=y;y=s;}if(a[x].back==y) {a[a[x].front].back=y;a[a[y].back].front=x;list t=list(a[x].front,a[x].back);a[x].front=y;a[x].back=a[y].back;a[y].front=t.front;a[y].back=x;} else {a[a[x].back].front=y;a[a[x].front].back=y;a[a[y].back].front=x;a[a[y].front].back=x;list t=list(a[x].front,a[x].back);a[x].front=a[y].front;a[x].back=a[y].back;a[y].front=t.front;a[y].back=t.back;}}if(opr==4) rev^=1;}long long ans=0;int now=0,odd=false;if(rev==1) {for(int i=1; i<=n; i++) {a[i]=list(a[i].back,a[i].front);}}for(int i=1; i<=n; i++) {if(a[i].front==100001) now=i;}while(now!=100001) {odd^=1;if(odd==true)ans+=now;now=a[now].back;}printf("Case %d: %lld\n",++T,ans);}return 0;}


原创粉丝点击