Boxes in a Line

Description

You have n boxes in a line on the table numbered 1 . . . n from left to right. Your task is to simulate 4

kinds of commands:
• 1 X Y : move box X to the left to Y (ignore this if X is already the left of Y )
• 2 X Y : move box X to the right to Y (ignore this if X is already the right of Y )
• 3 X Y : swap box X and Y
• 4: reverse the whole line.
Commands are guaranteed to be valid, i.e. X will be not equal to Y .
For example, if n = 6, after executing 1 1 4, the line becomes 2 3 1 4 5 6. Then after executing
2 3 5, the line becomes 2 1 4 5 3 6. Then after executing 3 1 6, the line becomes 2 6 4 5 3 1.
Then after executing 4, then line becomes 1 3 5 4 6 2


Input

There will be at most 10 test cases. Each test case begins with a line containing 2 integers n, m
(1 ≤ n, m ≤ 100, 000). Each of the following m lines contain a command.


Output

For each test case, print the sum of numbers at odd-indexed positions. Positions are numbered 1 to n
from left to right.


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

这道题还是链表的应用,但是显然单向链表已经不行了,所以我们使用双向链表,同样我们不用指针来做,还是用数组——用right【i】和left【i】来表示i的左边和右边的数。执行前三条指令时,我们只需要修改数字之间的链接即可,下面这个函数可以起到这个作用:

void link(int L,int R)

{

right【L】=R;left【R】=L;
}

在双向链表这样复杂的结构中,常常编写辅助函数来设置链接关系。

第四个反转操作比较麻烦,这时候我们可以用加标记的方法来处理,并不用真的执行这个操作。我们只需标记下来反转了没,如果反转了,则1、2操作将会对换(即x放到y的左边就会变成放到y的右边,因为反转过后相对位置就会改变)。代码如下:

#include<cstdio>
using namespace std;
const int maxn=100000+5;
int main()
{
	int n,com,count=0;
	while(scanf("%d%d",&n,&com)==2)
	{
		int right[maxn],left[maxn];
		for(int i=0;i<=n;i++) right[i]=i+1;
		for(int i=n;i>0;i--) left[i]=i-1;
		int vir=0;
		for(int i=0;i<com;i++)
		{
			int m,x,y;
			scanf("%d",&m);
			if(m==4) vir=(!vir);
			else
			{
				scanf("%d%d",&x,&y);
				if(vir&&m!=3) m=3-m;
				if(m==1&&right[x]==y) continue;
				if(m==2&&right[y]==x) continue;
				int lx=left[x],rx=right[x],ly=left[y],ry=right[y];
				if(m==1)
				{
					right[lx]=rx;left[rx]=lx;
					right[ly]=x;left[x]=ly;
					right[x]=y;left[y]=x;
				}
				if(m==2)
				{
					right[lx]=rx;left[rx]=lx;
					right[y]=x;left[x]=y;
					right[x]=ry;left[ry]=x;
				}
				if(m==3)
				{
					if(right[x]==y)
					{
						right[lx]=y;left[y]=lx;
						right[y]=x;left[x]=y;
						left[ry]=x;right[x]=ry;
					}
					else if(right[y]==x)
					{
						right[ly]=x;left[x]=ly;
						right[x]=y;left[y]=x;
						left[rx]=y;right[y]=rx;
					}
					else
					{
						right[lx]=y;left[y]=lx;
						left[rx]=y;right[y]=rx;
						right[ly]=x;left[x]=ly;
						left[ry]=x;right[x]=ry;
					}
				}
			}
		}
		int b=0;
		long long int ans=0;
		for(int i=1;i<=n;i++)
		{
			b=right[b];
			if(i%2!=0) ans+=b;
		}
		if(vir&&(n%2==0)) ans=(long long int)n*(n+1)/2-ans;
		printf("Case %d: %lld\n",++count,ans);
	}
	return 0;
} 
我犯了两个错误,导致代码迟迟不能通过:

1.long long的占位符写成了%d

2.

                              1.  if(vir&&m!=3) m=3-m;
			      2.  if(m==1&&right[x]==y) continue;
			      3.  if(m==2&&right[y]==x) continue;

上面三条语句的顺序写成了2、3、1.细想一下,如果执行了反转操作,那么相对位置就会改变,那么如果输入的命令是把x放到y的左边,初始时为:x,y而执行了反转后为:y,x,此时当然可以执行把x放到左边,但是如果第一条语句在最后的时候,就会continue,当然是错的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值