UVA - 12657 Boxes in a Line

/*
  小白书上给出了代码,但是对于代码的解释,不是特别详细,这个博客就比较详细,基本写出了几种分类的依据和考虑,以及如何对于哪些情况,要特别拿出来特判
  博客:
  http://blog.csdn.net/acmore_xiong/article/details/47753589
  

  注意:
  1. 虽然小白书上定义的数组名是 left 和 right ,但是不太建议用这两个,因为小白书给出的是C的代码,但如果用到C++  left和right会和 <iostream>头文件中,用于控制IO输入输出格式的 left 和 out 同名,引起二义性,可以将数组名改为大写来解决这个问题
  
  或者,就不用<iostream>头文件了,这题用它主要是想运用自带的swap函数,但是如果只包含 <algorithm>头文件,也能达到同样的效果
  
  
  收获:(具体见小白书P145-148)
  1. 双向链表等复杂的链式结构中,往往会编写一些辅助函数来设置链接关系,例如该题的 link函数
  
  2. 如果数据结构上某一个操作耗时,可以加标记来处理,而不用真的执行那个操作。但同时,该数据结构所有其他操作都要考虑这个标记
  
  3. 复杂链式结构往往容易写错,编码结束后,为了确保程序准确性,测试和调试往往要交替进行
  
  4. 对拍--对于某份可能出错的程序,应该再编写一份速度可能不优,但正确性能得到绝对保证的另一份代码。利用数据生成器(随机数生成函数等),来生成随机数据,执行两个程序,比较它们的结果(简易版本越简单越好,不重在速度,重在正确性)
  
  5.
  数据复杂性会增大调试难度。找到使程序出错的数据后,应尝试简化数据,或者用更小的参数调用数据生成器,找到更简单的错误数据
  
*/




#include <cstdio>
#include <algorithm> 
using namespace std;
const int maxn = 1e5 + 10;
int left[maxn], right[maxn], n, m;

void link(int L, int R)
{
	right[L] = R; left[R] = L;
}

int main()
{
	int kase = 0;
	while (scanf("%d%d", &n, &m) == 2)
	{
		for (int i = 1; i <= n; i++)
		{
			left[i] = i - 1;
			right[i] = (i + 1) % (n + 1);
		}
		left[0] = n;
		right[0] = 1;//实现双向链表
		
		int op, X, Y, inv = 0;
		
		while (m--)
		{
			scanf("%d", &op);
			if (op == 4) inv = !inv;
			else
			{
				scanf("%d%d", &X, &Y);
				if (op == 3 && right[Y] == X) swap(X, Y);
				if (op != 3 && inv) op = 3 - op;
				if (op == 1 && left[Y] == X) continue;
				if (op == 2 && right[Y] == X) continue;
				//注意:后两条语句一定要放前两条语句的后面
				//因为我们对 4操作是加了标记的,所以,所有其他操作,都要考虑那个标记的影响,之前满足后两个if还不算,一定要在考虑了4的标记的可能影响以后,仍然满足if,才是真正能continue的情况 
				
				int LX = left[X], RX = right[X], LY = left[Y], RY = right[Y];
				if (op == 1)
				{
					link(LX, RX); link(LY, X); link(X, Y);
				}
				else if (op == 2)
				{
					link(LX, RX); link(Y, X); link(X, RY);
				}
				else if (op == 3)
				{
					if (right[X] == Y)
					{
						link(LX, Y); link(Y, X); link(X, RY);
						//在这种情况下,可画图发现,X == LY, Y == RX,所以这里的X和Y,可以分别用LY和RX替换掉
					}
					else
					{
						link(LX, Y); link(Y, RX); link(LY, X); link(X, RY);
					}
				}
			}
		}
		
		int b = 0;
		long long ans = 0;
		for (int i = 1; i <= n; i++)
		{
			b = right[b];
			if (i % 2) ans += b;
		}
		
		if (inv && n % 2 == 0) ans = (long long)n * (n + 1) / 2 - ans;
		printf("Case %d: %lld\n", ++kase, ans);
	}
}


posted @ 2017-09-23 23:51  mofushaohua  阅读(113)  评论(0编辑  收藏  举报