1329: 一行盒子
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 740 Solved: 145
[Submit][Status][Web Board]
Description
你有一行盒子,从左到右依次编号为1, 2, 3,…, n。你可以执行四种指令:
1 X Y表示把盒子X移动到盒子Y左边(如果X已经在Y的左边则忽略此指令)。
2 X Y表示把盒子X移动到盒子Y右边(如果X已经在Y的右边则忽略此指令)。
3 X Y表示交换盒子X和Y的位置。
4 表示反转整条链。
指令保证合法,即X不等于Y。例如,当n=6时在初始状态下执行1 1 4后,盒子序列为2 3 1 4 5 6。接下来执行2 3 5,盒子序列变成2 1 4 5 3 6。再执行3 1 6,得到2 6 4 5 3 1。最终执行4,得到1 3 5 4 6 2。
Input
输入包含不超过10组数据,每组数据第一行为盒子个数n和指令条数m(1<=n,m<=100,000),以下m行每行包含一条指令。
Output
每组数据输出一行,即所有奇数位置的盒子编号之和。位置从左到右编号为1~n。
Sample Input
6 4 1 1 4 2 3 5 3 1 6 4 6 3 1 1 4 2 3 5 3 1 6 100000 1 4
Sample Output
Case 1: 12 Case 2: 9
Case 3: 2500050000
难点在于第四种操作,第四种操作是反转,效果是前后继交换了,其实根本不需要操作,只需记录反转的 次数就行了。反转次数为奇数时,
flag=1的操作变成flag=2的操作,flag=2的操作变成flag=1的操作,其他的不变。
因为反转后,一个数的前面变成后面,后面变成前面。还有就是构成环,方便找到起点和终点。
AC代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<queue> 6 #include<string> 7 #include<cmath> 8 using namespace std; 9 int *tmp1,*tmp2; 10 const int N = 1e5+10; 11 int LEFT[N],RIGHT[N]; 12 void swap(int a,int b) 13 { 14 RIGHT[a] = b; 15 LEFT[b] = a; 16 } 17 int main() 18 { 19 int cas = 1; 20 int T,cnt,nest,flag,m,n,x,y; 21 while(~scanf("%d %d",&m,&n)) 22 { 23 for(int i=1;i<=m;i++)//预处理 24 { 25 LEFT[i] = i-1; 26 RIGHT[i] = i+1; 27 } 28 RIGHT[m] = 0; 29 cnt = 0; 30 while(n--) 31 { 32 scanf("%d",&flag); 33 if(flag != 4) scanf("%d %d",&x,&y); 34 else cnt++; 35 if((cnt&1) && flag<3) flag = 3 - flag; 36 if(flag == 1 && LEFT[y]!=x) 37 { 38 swap(LEFT[x],RIGHT[x]); 39 swap(LEFT[y],x); 40 swap(x,y); 41 } 42 else if(flag == 2 && RIGHT[y]!=x) 43 { 44 swap(LEFT[x],RIGHT[x]); 45 swap(x,RIGHT[y]); 46 swap(y,x); 47 } 48 else if(flag == 3) 49 { 50 if(RIGHT[x] == y)//两者在挨着; 51 { 52 swap(LEFT[x],y); 53 swap(x,RIGHT[y]); 54 swap(y,x); 55 } 56 else if(LEFT[x] == y) 57 { 58 swap(LEFT[y],x); 59 swap(y,RIGHT[x]); 60 swap(x,y); 61 } 62 else 63 { 64 int t1 = LEFT[x],t2 = RIGHT[x],t3 = LEFT[y],t4 = RIGHT[y]; 65 swap(t1,y); 66 swap(y,t2); 67 swap(t3,x); 68 swap(x,t4); 69 70 } 71 } 72 } 73 long long ans = 0; 74 if(cnt&1) //翻转一下 75 { 76 tmp2 = RIGHT; 77 tmp1 = LEFT; 78 } 79 else { 80 tmp2 = LEFT; 81 tmp1 = RIGHT; 82 } 83 for(int i=1;i<=m;i++) 84 { 85 if(tmp2[i] == 0)//寻找第一位 86 { 87 for(int k=1;i;i = tmp1[i],k++) 88 if(k&1) ans = ans+i; 89 printf("Case %d: %lld ",cas++,ans); 90 break; 91 } 92 } 93 } 94 return 0; 95 }