列车调度(Train)

Description
Figure 1 shows the structure of a station for train dispatching.
<img src="https://img-blog.csdn.net/20160515124921130?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />

Figure 1

In this station, A is the entrance for each train and B is the exit. S is the transfer end. All single tracks are one-way, which means that the train can enter the station from A to S, and pull out from S to B. Note that the overtaking is not allowed. Because the compartments can reside in S, the order that they pull out at B may differ from that they enter at A. However, because of the limited capacity of S, no more that m compartments can reside at S simultaneously.

Assume that a train consist of n compartments labeled {1, 2, …, n}. A dispatcher wants to know whether these compartments can pull out at B in the order of {a1, a2, …, an} (a sequence). If can, in what order he should operate it?

Input
Two lines:

1st line: two integers n and m;

2nd line: n integers separated by spaces, which is a permutation of {1, 2, …, n}. This is a compartment sequence that is to be judged regarding the feasibility.

Output
If the sequence is feasible, output the sequence. “Push” means one compartment goes from A to S, while “pop” means one compartment goes from S to B. Each operation takes up one line.

If the sequence is infeasible, output a “no”.

Example 1
Input

5 2
1 2 3 5 4
Output

push
pop
push
pop
push
pop
push
push
pop
pop
Example 2
Input

5 5
3 1 2 4 5
Output

No
Restrictions
1 <= n <= 1,600,000

0 <= m <= 1,600,000

Time: 2 sec

Memory: 256 MB

描述
某列车调度站的铁道联接结构如Figure 1所示。

其中,A为入口,B为出口,S为中转盲端。所有铁道均为单轨单向式:列车行驶的方向只能是从A到S,再从S到B;另外,不允许超车。因为车厢可在S中驻留,所以它们从B端驶出的次序,可能与从A端驶入的次序不同。不过S的容量有限,同时驻留的车厢不得超过m节。

设某列车由编号依次为{1, 2, ..., n}的n节车厢组成。调度员希望知道,按照以上交通规则,这些车厢能否以{a1, a2, ..., an}的次序,重新排列后从B端驶出。如果可行,应该以怎样

的次序操作?

输入
共两行。

第一行为两个整数n,m。

第二行为以空格分隔的n个整数,保证为{1, 2, ..., n}的一个排列,表示待判断可行性的驶出序列{a1,a2,...,an}。

输出
若驶出序列可行,则输出操作序列,其中push表示车厢从A进入S,pop表示车厢从S进入B,每个操作占一行。

若不可行,则输出No。

样例
见英文题面

限制
1 ≤ n ≤ 1,600,000

0 ≤ m ≤ 1,600,000

时间:2 sec

空间:256 MB



/*
给出一组数据,比如例子中的
3 1 2 4 5
给出的顺序是B中的顺序,而A中的顺序是将给出的序列从小到大排序后的序列。
如何利用S这个中转站(也就是栈)将A中的顺序变成B中的顺序,不能输出no
*/
#include "stdio.h"

#define N 1600000

int A[N], S[N], B[N];
char *P[N];

void quickSort(int lo, int high)//将A中的序列用快排排好
{
	int lo_t = lo, high_t = high;
	int temp = A[lo];
	if (lo > high)
	{
		return;
	}
	while (lo_t != high_t)
	{
		while (A[high_t] >= temp && lo_t < high_t)
		{
			high_t--;
		}
		while (A[lo_t] <= temp && lo_t < high_t)
		{
			lo_t++;
		}

		if (lo_t < high_t)
		{
			int temp = A[lo_t];
			A[lo_t] = A[high_t];
			A[high_t] = temp;
		}
	}
	A[lo] = A[lo_t];
	A[lo_t] = temp;

	quickSort(lo, lo_t - 1);
	quickSort(lo_t + 1, high);
	return;
}

void push(int S[], int si, int value)//压入栈中
{
	S[si] = value;
}

int check(int num, int *S, int si)//用二分进行查找
{
	int first = 1, last = si, middle;
	while (first <= last)
	{
		middle = (first + last) / 2;
		if (num > S[middle])
		{
			first = middle + 1;
		}
		else if (num < S[middle])
		{
			last = middle;
		}
		else
		{
			return 0;
		}
	}
	return 1;
}
int main()
{
	int n, m;
	int flagn = 1, end = 1, i;

	scanf("%d %d", &n, &m);
	for (i = 1; i <= n; i++)
	{
		scanf("%d", A + i);
		B[i] = A[i];
	}

	quickSort(1, n);

	int si = 1, bi = 1, pi = 1, j;
	for (j = 1; j <= n; j++)
	{
		if (si <= m)
		{
			push(S, si, A[j]);
			P[pi++] = "push\n";
			while (si >= 1 && bi <= n)
			{
				if (S[si] == B[bi])
				{
					P[pi++] = "pop\n";
					bi++;
					si--;
				}
				else if (!check(B[bi], S, si))//这里拿给出的第二个案例推一下就可以明白了
				{
					printf("No\n");
					return 0;
				}
				else
				{
					break;
				}
			}
			si++;
		}
		else
		{
			printf("No\n");
			flagn = 0;
			break;
		}
	}
	if (flagn)
	{
		int k;
		for (k = bi; k <= n; k++)
		{
			if (B[k] == S[--si])
			{
				P[pi++] = "pop\n";
			}
			else
			{
				end = 0;
				printf("No\n");
				break;
			}
		}
		if (end == 1)
		{
			int i;
			for (i = 1; i < pi; i++)
			{
				printf("%s", P[i]);
			}
		}
	}
	getchar();
	getchar();
	return 0;
}
这个只能过掉85%的测试案例,最后三个超时了,毕竟小菜鸟水平有限啊。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值