P1160 队列安排(C++_双向链表_队列_优化EX)

题目描述

一个学校里老师要将班上N个同学排成一列,同学被编号为1∼N,他采取如下的方法:

先将1号同学安排进队列,这时队列中只有他一个人;

2−N号同学依次入列,编号为i的同学入列方式为:老师指定编号为i的同学站在编号为1∼(i−1)中某位同学(即之前已经入列的同学)的左边或右边;

从队列中去掉M(M

在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。

输入格式

第1行为一个正整数N,表示了有N个同学。

第2−N行,第ii行包含两个整数k,p,其中k为小于ii的正整数,p为0或者1。若p为0,则表示将i号同学插入到k号同学的左边,p为1则表示插入到右边。

第N+1行为一个正整数M,表示去掉的同学数目。

接下来M行,每行一个正整数x,表示将x号同学从队列中移去,如果x号同学已经不在队列中则忽略这一条指令。

输出格式

1行,包含最多N个空格隔开的正整数,表示了队列从左到右所有同学的编号,行末换行且无空格。

输入输出样例

输入 #1

4
1 0
2 1
1 0
2
3
3

输出 #1

2 4 1

说明/提示

样例解释:
将同学2插入至同学1左边,此时队列为:
21
将同学3插入至同学2右边,此时队列为:
231
将同学4插入至同学1左边,此时队列为:
2341
将同学3从队列中移出,此时队列为:
241
同学3已经不在队列中,忽略最后一条指令
最终队列:
241

数据范围

对于20%的数据,有N≤10;
对于40%的数据,有N≤1000;
对于100%的数据,有N,M≤100000。

非AC 源码(AC源码在下面)

我是信了洛谷算法标签的邪,我居然真的模拟了队列结构,被find()坑死,所以也理所当然的TLE了三个点。

#include
using namespace std;
int main()
{
	int n, num = 0;
	vector<int>a;
	cin >> n;
	a.push_back(1);
	for (int i = 1; i < n; i++)
	{
		int k, p;
		cin >> k >> p;
		if (p == 0)
			a.insert(find(a.begin(), a.end(), k), i + 1);
		else
			a.insert(find(a.begin(), a.end(), k) + 1, i + 1);
	}
	int m;
	cin >> m;
	for (int i = 0; i < m; i++)
	{
		int k;
		cin >> k;
		vector<int>::iterator temp= find(a.begin(), a.end(), k);
		if (temp != a.end())
			a.erase(temp);
	}
	for (int i = 0; a.begin() + i != a.end(); i++)
		cout << a[i] << " ";
	return 0;
}

AC源码

听题解区dalao说单链表会超时,但双向链表不会,所以我就去用了双向链表,结果TLE得我脑阔疼(我还是太天真了 ),逼得我加了两层优化,也就是一个used数组还有一个better数组,better数组是后来加的也是重点,所以我觉得used数组可以删掉,你要是看到这段话的话可以试着删掉used 数组的相关操作,这样代码也简洁些~

#include
using namespace std;
int used[100001];//优化删除过程中的查找
class node
{
public:
	int id;
	node* front=NULL, * next=NULL;
};
node* better[100001];//优化整体查找过程
node* head = new node;
node* search(int k)//查找元素
{
	/*node* p = head;
	while (p)
	{
		if (p->id == k)
			return p;
		p = p->next;
	}
	return nullptr;*/
	return better[k];
}
int main()
{
	memset(used, 0, sizeof(used));
	int n;
	cin >> n;
	head->id = 1;
	used[1] = 1;
	better[1] = head;
	for (int i = 2; i <= n; i++)
	{
		used[i] = 1;
		int k, p;
		cin >> k >> p;
		node* q = new node;
		if (i == 2)
			q->front = head;
		q->id = i;
		node* temp = search(k);
		if (temp)
			if (p == 0)//插入左侧
			{
				if (temp != head)
				{
					q->next = temp;
					q->front = temp->front;
					temp->front->next = q;
					temp->front = q;
				}
				else
				{
					q->next = head;
					head->front = q;
					head = q;
					q->front = nullptr;
				}
			}
			else//插入右侧
			{
				if (temp->next != nullptr)
				{
					q->next = temp->next;
					q->front = temp;
					temp->next->front = q;
					temp->next = q;
				}
				else
				{
					q->front = temp;
					temp->next = q;
				}
			}
		better[i] = q;
	}
	int m;
	cin >> m;
	for (int i = 0; i < m; i++)
	{
		int k;
		node* temp=nullptr;
		cin >> k;
		if (used[k] == 0)//优化
			temp = nullptr;
		else
			temp = search(k);
		if (temp)
		{
			if (temp != head)
				if (temp->next != nullptr)
				{
					temp->front->next = temp->next;
					temp->next->front = temp->front;
				}
				else
					temp->front->next = nullptr;
			else
				head = head->next;
			used[k] = 0;
			better[k] = nullptr;
		}
	}
	node* p = head;
	while (p)
	{
		cout << p->id << " ";
		p = p->next;
	}
	return 0;
}

你可能感兴趣的:(模拟,洛谷)