P1160 队列安排

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

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

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

从队列中去掉M(M<N)M(M<N)个同学,其他同学位置顺序不变。

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

输入输出格式
输入格式:
第11行为一个正整数NN,表示了有NN个同学。

第2-N2−N行,第ii行包含两个整数k,pk,p,其中kk为小于ii的正整数,pp为00或者11。若pp为00,则表示将ii号同学插入到kk号同学的左边,pp为11则表示插入到右边。

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

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

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

输入输出样例
输入样例#1:
4
1 0
2 1
1 0
2
3
3
输出样例#1:
2 4 1

扫描二维码关注公众号,回复: 6101949 查看本文章

说明
样例解释:

将同学22插入至同学11左边,此时队列为:

2 121

将同学33插入至同学22右边,此时队列为:

2 3 1231

将同学44插入至同学11左边,此时队列为:

2 3 4 12341

将同学33从队列中移出,此时队列为:

2 4 1241

同学33已经不在队列中,忽略最后一条指令

最终队列:

2 4 1241

数据范围

对于20%20%的数据,有N≤10N≤10;

对于40%40%的数据,有N≤1000N≤1000;

对于100%100%的数据,有N, M≤100000N,M≤100000。

这道题目我首先用的是链表做的,超时了
只过了两个点

#include <bits/stdc++.h>
#include <malloc.h>
using namespace std;
typedef int DataType;
typedef struct Node{
	DataType data;
	struct Node *next;
}Node,*BNode;
int a[100005];
void initNode(BNode *head)
{
	*head = (Node*)malloc(sizeof(Node));
	Node *p = (Node*)malloc(sizeof(Node));
	p->data = 1;
	p->next = NULL;
	(*head)->next = p;
}
void insert1(BNode *head,int k,int x)
{
	int n = 0;
	BNode p = (*head)->next,q,t;
	q = (BNode)malloc(sizeof(Node));
	q->data = x;
	q->next = NULL;
	t = (*head);
	while(p->data != k ){
		t = p;
		n++;
		p = p->next;
	}
	if(n == 0){
		q->next = p;
		(*head)->next = q;
	}else {
		t->next = q;
		q->next = p;
	}
}
void insert2(BNode *head,int k,int x)
{
	BNode p = (*head)->next,q;
	q = (BNode)malloc(sizeof(Node));
	q->data = x;
	q->next = NULL;
	while(p->data != k){
		p = p->next;	
	}
	BNode t = p->next;
	p->next = q;
	q->next = t;
}
int main()
{
	int n;
	BNode head,p;
	//对链表进行初始化
	initNode(&head);
	scanf("%d",&n);
	for(int i = 2;i <= n;i++){
		int k,p;
		scanf("%d %d",&k,&p);
		if(p == 0){
			insert1(&head,k,i);
		}else {
			insert2(&head,k,i);
		}
	}
	int m;
	scanf("%d",&m);
	for(int i = 0;i < m;i++){
		int x;
		scanf("%d",&x);
		a[x] = 1;
	}
	p = head->next;
	while(p != NULL){
		DataType x;
		x = p->data;
		if(a[x] == 0)
		printf("%d ",x);
		p = p->next;
	}
    return 0;
}

然后看到有个用的是模拟,我也就尝试了下,AC了

#include <bits/stdc++.h>
/*
  第二列表示这是第i个数
  第一列表示这是第i个数左边数的值
  第三列表示这是第i个数右边数的值 
*/
int a[100005][3];
/*
  用来记录某个数是否被删除
  x没被删除则b[x] = 0;否则b[x] = 1; 
*/
int b[100005];
int main()
{
	int n;
	/**/
	a[1][1] = 1;
	scanf("%d",&n);
	for(int i = 2;i <= n;i++){
		/**/
		a[i][1] = i;
		int k,p;
		scanf("%d %d",&k,&p);
		/*
		这是模拟的过程,可以手动的算出来
		自己动手,要不然看不懂 
		*/
		if(p == 0){
			a[i][2] = k;
			a[i][0] = a[a[i][2]][0];
			a[a[k][0]][2] = i;
			a[k][0] = i; 
		}else {
			a[i][0] = k;
			a[i][2] = a[a[i][0]][2];
			a[a[k][2]][0] = i;
			a[k][2] = i;
		}
	}
	int m;
	scanf("%d",&m);
	for(int i = 0;i < m;i++){
		int x;
		scanf("%d",&x);
		b[x] = 1;
	}
	int k = 1;
	while(a[k][0] != 0) k++;
	while(k != 0){
		if(b[a[k][1]] == 0){
			printf("%d ",a[k][1]);
		}
		k = a[k][2];
	}
	/*
	for(int i = 1;i <= n;i++){
		printf("%d %d %d\n",a[i][0],a[i][1],a[i][2]);
	}
	*/
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42868863/article/details/89217703