(双向链表之数组模拟)Boxes in a Line,第九届湖南省赛,B题

Problem B

Boxes in a Line

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

Output for the Sample Input

Case 1: 12
Case 2: 9
Case 3: 2500050000

The Ninth Hunan Collegiate Programming Contest (2013)
Problemsetter: Rujia Liu

Special Thanks: Feng Chen, Md. Mahbubul Hasan

题意抽象:

一开始有的n个盒子(编号从1到n),进行m个操作.操作共四种:

1 X Y :将X盒子移到Y左边.

2 X Y :将X盒子移到Y右边.

3 X Y :交换X,Y盒子的位置.

4 :将全部盒子逆排.

要求最后位置标号为奇数的盒子的编号之和.


双向链表的数组模拟,水题,debug跨越了几天,无语......最后写一个数据生成器和暴力程序才过了.

这里也贴出数据生成器和暴力程序,给曾经也遭受此题调试折磨的童鞋带来福音.(用数据生成器生成测试数据,然后用暴力程序读入数据并生成标准答案,将标准答案与你程序的答案比较就可以找到你程序的错误数据了,最后再debug......(答案比较可使用cmd命令行的文件比较))


AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100005;
typedef long long LL;
int L[maxn], R[maxn];
bool direct;
int N, M;
int op, X, Y;
void init()
{
	for (int i = 1; i <= N; i++)
	{
		L[i] = i - 1;
		R[i] = i + 1;
	}
	R[0] = 1;
	L[N + 1] = N;
	direct = true;
}
void connect(int a, int b)
{
	R[a] = b;
	L[b] = a;
}
void solve()
{
	if (!direct && (op == 1 || op == 2))
		op = 3 - op;
	if (op==3&&L[X] == Y)
		swap(X, Y);

	int lx = L[X], rx = R[X], ly = L[Y], ry = R[Y];
	switch (op)
	{
	case 1:
		if (X == L[Y])
			break;
		connect(lx, rx);
		connect(ly, X);
		connect(X, Y);
		break;
	case 2:
		if (X == R[Y])
			break;
		connect(lx, rx);
		connect(Y, X);
		connect(X, ry);
		break;
	case 3:
		if (R[X] == Y)
		{
			connect(lx, Y);
			connect(Y, X);
			connect(X, ry);
		}
		else
		{
			connect(lx, Y);
			connect(Y, rx);
			connect(ly, X);
			connect(X, ry);
		}
		break;
	case 4:
		direct = !direct;
		break;
	}
}
int main()
{
	/*freopen("f:\\input.txt", "r", stdin);
	freopen("f:\\test_in.txt", "r", stdin);
	freopen("f:\\OUT.txt", "w", stdout);*/
	int cas = 0;
	while (scanf("%d%d", &N, &M) != EOF)
	{
		init();
		while (M--)
		{
			cin >> op;
			if (op != 4)
				cin >> X >> Y;
			solve();
		}

		LL ans = 0;
		for (int p = R[0],i=1; i<=N; p = R[p],i++)
		if (i%2==1)
			ans += p;
		if (!direct&&N % 2 == 0)
			ans = (LL)N  / 2 * (LL)(N + 1)- ans;
		printf("Case %d: %lld\n", ++cas, ans);
	}
	return 0;
}

数据生成器:

#include <iostream>
#include <cstdio>
#include <cstring>
#include<ctime>
#include<cstdlib>
#include <algorithm>
using namespace std;
const int Test = 100;
const int mod = 1000;
typedef long long LL;

int main()
{
	freopen("f:\\test_in.txt", "w", stdout);
	//srand(time(NULL));
	for (int i = 0; i < Test; i++)
	{
		int n = 1 + rand() % mod;
		int m = 1 + rand() % mod;
		cout << n << " " << m << endl;
		for (int j = 0; j < m; j++)
		{
			int op = 1 + rand() % 4;
			if (op == 4)
			{
				cout << op << endl;
				continue;
			}
			else
			{
				int x = 1 + rand() % n;
				int y = 1 + rand() % n;
				while (x == y)
					y = 1 + rand() % n;
				cout << op << " " << x << " " << y << endl;
			}
		}
	}
}

暴力程序代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include<ctime>
#include<cstdlib>
#include <algorithm>
using namespace std;
const int maxn = 1005;
const int Test = 10;
const int mod = 10;
typedef long long LL;
int a[maxn],b[maxn];
int *find(int *beg, int *end, int val)
{
	while (*beg != val)
		beg++;
	return beg;
}
int main()
{
	freopen("f:\\test_in.txt", "r", stdin);
	freopen("f:\\test_out.txt", "w", stdout);
	int n, m;
	int cas = 0;
	while (cin >> n >> m)
	{
		//bool dir = true;
		memset(a, 0, sizeof(a));
		for (int i = 1; i <= n; i++)
			a[i] = i;
		for (int i = 0; i < m; i++)
		{
			int op, x, y,*xp,*yp,*p,tmp;
			cin >> op;
			if (op != 4)
			{
				cin >> x >> y;
				xp = find(a + 1, a + 1 + n, x);
				yp = find(a + 1, a + 1 + n, y);
				tmp = *xp;
				p = xp;
			}

			switch (op)
			{
			case 1:
				if (xp + 1 == yp)
					continue;

				if (xp < yp)
				{
					while (*(p + 1) != *yp)
					{
						*p = *(p + 1);
						p++;
					}
					*p = tmp;
				}
				else
				{
					while (*(p - 1) != *yp)
					{
						*p = *(p - 1);
						p--;
					}
					*p = *(p - 1);
					p--;
					*p = tmp;
				}
				break;
			case 2:
				if (xp - 1 == yp)
					continue;

				if (xp > yp)
				{
					while (*(p - 1) != *yp)
					{
						*p = *(p - 1);
						p--;
					}
					*p = tmp;
				}
				else
				{
					while (*(p + 1) != *yp)
					{
						*p = *(p + 1);
						p++;
					}
					*p = *(p + 1);
					p++;
					*p = tmp;
				}
				break;
			case 3:
				tmp = *xp;	*xp = *yp;	*yp = tmp;
				break;
			case 4:
				for (int j = n,k=1; j >= 1; j--,k++)
					b[j] = a[k];
				for (int j = 1; j <= n; j++)
					a[j] = b[j];
				break;
			}
		}
		LL ans = 0;
		for (int i = 1; i <= n; i+=2)
			ans += a[i];
		printf("Case %d: %lld\n", ++cas, ans);
	}

	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值